reduce()
方法对数组中的每个元素执行一个自定义
的reducer
函数(升序执行),将其结果汇总为单个返回值
const array = [1, 2, 3, 4];
const reducer = (accumulator, currentValue) => accumulator + currentValue;
const a = array.reduce(reducer); // 1 + 2 + 3 + 4
console.log(a); // 10
const b = array.reduce(reducer, 5); // 5 + 1 + 2 + 3 + 4
console.log(b); // 15
reducer
函数接收 4 个参数:
- Accumulator (acc) (累计器)
- Current Value (cur) (当前值)
- Current Index (idx) (当前索引)
- Source Array (src) (源数组)
您的 reducer 函数的返回值分配给累计器,该返回值在数组的每个迭代中被记住,并最后成为最终的单个结果值
语法
arr.reduce(callback(acc, cur, idx, src), initialValue)
参数:
callback
accumulator
累计器累计回调的返回值; 它是上一次调用回调时返回的累积值,或initialValue
(见于下方)currentValue
数组中正在处理的元素index (可选)
数组中正在处理的当前元素的索引。 如果提供了initialValue
,则起始索引号为0,否则从索引1起始array (可选)
调用reduce()
的数组
initialValue (可选)
- 作为第一次调用 callback函数时的第一个参数的值。 如果没有提供初始值,则将使用数组中的第一个元素。 在没有初始值的空数组上调用 reduce 将报错
返回值
函数累计处理的结果
应用
计算数组里所有值的和
var sum = [0,1,2,3].reduce(
(acc, cur)=> acc + cur,
0
)
console.log(sum)
累加对象数组里的值
const arr = [{x: 1}, {x: 2}, {x: 3}]
let sum = arr.reduce(
(acc, cur)=> acc + cur.x,
0
)
console.log(sum)
二维数组转化为一维数组
const arr = [[0, 1], [2, 3], [4, 5]]
let change = arr.reduce(
(acc, cur)=> acc.concat(cur),
[]
)
console.log(change)
计算数组中每个元素出现的次数
const names = ['Alice', 'Bob', 'Tiff', 'Bruce', 'Alice']
let count = names.reduce(
(allnames, name)=> {
if(name in allnames) {
allnames[name]++
}else {
allnames[name] = 1
}
return allnames
},
{}
)
console.log(count)
// console
[object Object] {
Alice: 2,
Bob: 1,
Bruce: 1,
Tiff: 1
}
按属性 object 分类
const people = [
{ name: 'Alice', age: 21 },
{ name: 'Max', age: 20 },
{ name: 'Jane', age: 20 }
];
let groupBy = (all, select)=> {
return all.reduce(
(acc, obj)=> {
let key = obj[select]
if(!acc[key]) {
acc[key] = []
}
acc[key].push(obj)
return acc
}, {}
)
}
let groupedPeople = groupBy(people, 'age')
console.log(groupedPeople)
// console
{
20: [
{ name: 'Max', age: 20 },
{ name: 'Jane', age: 20 }
],
21: [
{ name: 'Alice', age: 21 }
]
}
使用扩展运算符和initialValue绑定包含在对象数组中的数组
const friends = [{
name: 'Anna',
books: ['Bible', 'Harry Potter'],
age: 21
}, {
name: 'Bob',
books: ['War and peace', 'Romeo and Juliet'],
age: 26
}, {
name: 'Alice',
books: ['The Lord of the Rings', 'The Shining'],
age: 18
}];
let allbooks = friends.reduce(
(acc, cur)=> [...acc, ...cur.books],
[]
);
console.log(allbooks);
// console
["Bible", "Harry Potter", "War and peace", "Romeo and Juliet", "The Lord of the Rings", "The Shining"]
数组去重
const arr = ['a', 'b', 'a', 'b', 'c', 'e', 'e', 'c', 'd', 'd', 'd', 'd'];
let newArr = arr.reduce(
(acc, cur)=> {
if(acc.indexOf(cur) === -1) {
acc.push(cur)
}
return acc
}, []
)
console.log(newArr) // ["a", "b", "c", "e", "d"]
// 同上方法,判断 acc 数组里有没有 cur ,没有就往里加
let arr = [1,2,1,2,3,5,4,5,3,4,4,4,4];
let newArr = arr.sort().reduce(
(acc, cur)=> {
if(acc.indexOf(cur) === -1) {
acc.push(cur)
}
return acc
}, []
)
console.log(newArr) // [1, 2, 3, 4, 5]
// 判断 acc 初始值为空,或者 acc 最后的值不为 cur (arr数组中最后一项)
let arr = [1,2,1,2,3,5,4,5,3,4,4,4,4];
let result = arr.sort().reduce((init, current) => {
if(init.length === 0 || init[init.length-1] !== current) {
init.push(current);
}
return init;
}, []);
console.log(result); // [1,2,3,4,5]
按顺序运行 Promise
let runPromiseInSequence = (arr, input) => arr.reduce(
(promiseChain, currentFun) => promiseChain.then(currentFun),
Promise.resolve(input)
)
let p1 = (a) => (new Promise((res, rej)=> {
res(a*5)
}))
let p2 = (a) => (new Promise((res, rej)=> {
res(a*2)
}))
let f3 = (a) => a * 3
let f4 = (a) => a * 4
const promiseArr = [p1, p2, f3, f4]
runPromiseInSequence(promiseArr, 10)
.then(console.log) // 1200