乐趣区

关于reduce:由浅入深讲解数组的reduce用法

数组中的 reduce 犹如一只魔法棒,通过它能够做一些黑科技一样的事件。本文从 api 解说到个别用法再到高级用法,由浅入深的讲一讲数组中的 reduce。MDN 链接

Array.prototype.reduce

reduce 的 api 是这样的,

reduce(callback(accumulator, currentValue[, index, array])[,initialValue])

  • Callback

    • accumulator 积攒的值
    • currentValue 以后值
    • index 以后下标
    • array 以后数组
  • initialValue 初始值

reduce 承受两个参数,回调函数和初识值,初始值是可选的。回调函数承受 4 个参数:积攒值、以后值、以后下标、以后数组。
如果 reduce 的参数只有一个,那么积攒值一开始是数组中第一个值,如果 reduce 的参数有两个,那么积攒值一开始是出入的 initialValue 初始值。
而后在每一次迭代时,返回的值作为下一次迭代的 accumulator 积攒值。

重要阐明:如果未设置 initialValue,那么 reduce 将应用您的第一个数组值作为第一次迭代的 accumulator,从第二个数组元素上开始循环,从 index= 1 开始(如果有的话)

以下是 reduce 的几种理论利用。

1. 将数组转化为对象

将上面的数组转成以 id 为 key 的对象。


const userList = [
    {
        id: 1,
        username: 'john',
        sex: 1,
        email: 'john@163.com'
    },
    {
        id: 2,
        username: 'jerry',
        sex: 1,
        email: 'jerry@163.com'
    },
    {
        id: 3,
        username: 'nancy',
        sex: 0,
        email: ''
    }
];

let objUserList = userList.reduce(keyByUserNameReducer, {})

function keyByUserNameReducer(acculumator, currentValue, currentIndex, array) {return {...acculumator, [currentValue.id]: currentValue}
}

console.log(objUserList)

// {//    '1': { id: 1, username: 'john', sex: 1, email: 'john@163.com'},
//    '2': {id: 2, username: 'jerry', sex: 1, email: 'jerry@163.com'},
//    '3': {id: 3, username: 'nancy', sex: 0, email: ''}
// }

2. 将小数组开展成大数组

将上面数组依照逗号宰割.


const fileLines = [
    'Inspector Algar,Inspector Bardle,Mr. Barker,Inspector Barton',
    'Inspector Baynes,Inspector Bradstreet,Inspector Sam Brown',
    'Monsieur Dubugue,Birdy Edwards,Inspector Forbes,Inspector Forrester',
    'Inspector Gregory,Inspector Tobias Gregson,Inspector Hill',
    'Inspector Stanley Hopkins,Inspector Athelney Jones'
];

let commaArray = fileLines.reduce(function (acculumator, currentValue, currentIndex, array) {return acculumator.concat(currentValue.split(/,/g))
}, [])
console.log(commaArray)
/*
[
    'Inspector Algar',
    'Inspector Bardle',
    'Mr. Barker',
    'Inspector Barton',
    'Inspector Baynes',
    'Inspector Bradstreet',
    'Inspector Sam Brown',
    'Monsieur Dubugue',
    'Birdy Edwards',
    'Inspector Forbes',
    'Inspector Forrester',
    'Inspector Gregory',
    'Inspector Tobias Gregson',
    'Inspector Hill',
    'Inspector Stanley Hopkins',
    'Inspector Athelney Jones'
  ]
*/

3. 用 reduce 实现 flatMap


// 数组的 flatMap
// flatMap 的底层的操作:先应用 map 操作,而后对失去的数组仅开展一层再失去一个数组
const arr = ["今天天气不错", ""," 早上好 "];
let flatMapArr = arr.flatMap((item, index) => {return item.split("")
})
console.log(flatMapArr) // ['今', '天', '天','气', '不', '错','早', '上', '好']

// 应用数组的 reduce 实现数组的 flatMap
let reduceFlatMap = arr.reduce(function (acculumator, currentValue, currentIndex, array) {return [...acculumator, ...currentValue.split('')]
}, [])
console.log(reduceFlatMap) // ['今', '天', '天','气', '不', '错','早', '上', '好']

4. 按程序执行异步函数

依据 userList 数组的 name 属性去顺次申请数据。


let asyncReducer = userList.reduce(async function (acculumator, currentValue, currentIndex, array) {const obj = await acculumator.then()
    let re = await new Promise((resolve, reject) => {
        // 用 setTimeout 模仿申请数组
        setTimeout(() => {resolve(`to=>${currentValue.username}`)
        }, 1000)
    })
    return {...obj, [currentValue.username]: re}

}, Promise.resolve({}))
asyncReducer.then(res => {console.log(res)
})

// 3s 之后打印:// {john: 'to=>john', jerry: 'to=>jerry', nancy: 'to=>nancy'}

总结:

  • 记住在解决对象数组时要指定一个 initialValue
  • 数字数组应用 reduce 代码洁净,请尽量不要把 reduce 函数过于简单
  • 不要遗记在回调函数中返回,否则最初失去的值将可能呈现谬误
  • 回调函数的第三个参数 index 拜访迭代次数
  • reduce 解决时会跳过数组空值
退出移动版