优雅的使用reduce(),reduce()高级技巧

562 阅读2分钟

reduce() 浅谈

谈起reduce(),其实我一直在思考一个问题,现在也还困扰着我。reduce()可以实现的功能for都能搞定,或者forEach有些时候也能搞定,那么为什么还要使用reduce(),不得其解,但是我觉得,它让我的代码变得足够优雅整洁,这不就够了吗?

语法

arr.reduce(callback, [initialValue])

reduce 为数组中的每一个元素依次执行回调函数,不包括数组中被删除或从未被赋值的元素,接受四个参数:初始值(或者上一次回调函数的返回值),当前元素值,当前索引,调用 reduce 的数组。

callback(执行数组中每个值得函数,包含四个参数)
1. previousValue (上一次调用回调返回的值,或者是提供的初始值(initialValue))
2. currentValue (数组中当前被处理的元素)
3. index (当前元素在数组中的索引)
4. array (调用reduce的数组)

initialValue (作为第一次调用callback的第一个参数)

实例解析初始化参数

ex1:

let arr = [1, 2, 3, 4]
let sum = arr.reduce(function(prev, cur, index, arr) {
    console.log(prev, cur, index)
    return prev + cur
})
console.log(arr, sum)

打印结果

1 2 1
3 3 2
6 4 3
[1, 2, 3, 4] 10

这个例子index是从0开始的,第一次 prev 的值使我们设置的初始值0,数组长度是4,reduce函数循环4次。

结论: 如果没有提供初始值,reduce会从索引1的地方开始执行callback方法,跳过第一个索引。如果提供初始值(initialValue),从提供的初始值,索引0开始。

注: 如果数组为空,会报错 TypeError: Reduce of empty array with no initial value 但是如果设置了初始值就不会报错。所以一般来说提供初始值会更安全。

reduce 的简单用法

最常见的数组求和,求乘积。

let arr = [1, 2, 3, 4]
let sum = arr.reduce((x, y) =>  x+y )
let mul = arr.reduce((x, y) => x*y )
console.log(sum) // 10
console.log(mul) // 24

reduce 的高级用法

  1. 计算数组中没个元素出现的次数
let name = ['Alice', 'Bob', 'Tiff', 'Bruce', 'Alice']
let nameNum = name.reduce((pre, cur) => {
    if (cur in pre) {
        pre[cur]++
    } else {
        pre[cur] = 1
    }
    return pre
},{})
console.log(nameNum) // {Alice: 2, Bob: 1, Tiff: 1, Bruce: 1}
  1. 数组去重
let arr = [1, 2, 3, 4, 4, 1]
let newArr = arr.reduce((pre, cur) => {
    if (!pre.includes(cur)) {
        return pre.concat(cur)
    } else {
        return pre
    }
},[])
console.log(newArr) // [1, 2, 3, 4]
  1. 将二维数组转化为一维
let arr = [[0, 1], [2, 3], [4, 5]]
let newArr = arr.reduce((pre, cur) => {
    return pre.concat(cur)
}, [])
console.log(newArr) // [0, 1, 2, 3, 4, 5]
  1. 将多维数组转化为一维
let arr = [[0, 1], [2, 3], [4, [5, 6]]]
let newArr = function (arr) {
    return arr.reduce((pre, cur) => pre.concat(Array.isArray(cur)? newArr(cur): cur), [])
}
console.log(newArr(arr)) // [0, 1, 2, 3, 4, 5, 6, 7]
  1. 对象里面的属性求和
let result = {
    { subject: 'Alice', score: 10 },
    { subject: 'Bob', score: 20 },
    { subject: 'Tiff', score: 30 }
}
let sum = result.reduce(function(pre, cur) {
    return cur.score + pre
}, 0)
console.log(sum) // 60

路漫漫其修远兮,吾将上下而求索