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 的高级用法
- 计算数组中没个元素出现的次数
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}
- 数组去重
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]
- 将二维数组转化为一维
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]
- 将多维数组转化为一维
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]
- 对象里面的属性求和
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
路漫漫其修远兮,吾将上下而求索