语法
reduce(callbackFn, initialValue?) //初始值可选
callbackFn(pre,cur,index,arr)
- 数组中的每个元素按序执行一个提供的 callbackFn 函数
- 每一次运行 callbackFn 会将先前元素的计算结果作为参数传入,最后将其结果汇总为单个返回值
不提供初始值的情况
1、空数组
[].reduce((pre,cur)=>{console.log(1111);return pre*cur})
结果:
2、长度为1
[1].reduce((pre,cur)=>{console.log(1111);return pre*cur})
结果:
3、长度不为1
[1,3].reduce((pre,cur)=>{console.log(1111);return pre*cur})
结果:
修改原数组的情况
1、增加元素
[1,2,3].reduce((pre,cur,index,arr)=>{if(index===0){arr.push(4)};return pre+cur},0)
结果:
2、修改已访问元素
[1,2,3].reduce((pre,cur,index,arr)=>{if(index===1){arr[0]=2};return pre+cur},0)
结果:
3、修改未访问元素
[1,2,3].reduce((pre,cur,index,arr)=>{if(index===1){arr[2]=2};return pre+cur},0)
结果:
边界情况
1、数组只有一个元素(不管位置)+未提供初始值
const arr=new Array(6)
arr[3]=1
arr.reduce((pre,cur)=>{console.log(1111);return pre*cur})
结果:
2、数组为空+提供初始值
[].reduce((pre,cur)=>{console.log(1111);return pre*cur},1)
结果:
使用场景
- 累加累乘
- 数据特性分组
- 求数组交集,并集,差集
- 返回对象指定键值
- 树形数据转为数组
使用场景1===>累加累乘
const a = [1, 2, 3, 4, 5]
const getToTal = (array) => {
return array.reduce((pre,cur)=>pre+cur,0)
}
const getMul = (array) => {
return array.reduce((pre,cur)=>pre*cur,1)
}
console.log(getToTal(a))
console.log(getMul(a))
使用场景2===>数据特性分组
const objectArray = [
{ id: 1, name: 'Alice', age: 25, occupation: 'Engineer', sex: '男' },
{ id: 2, name: 'Bob', age: 25, occupation: 'Doctor', sex: '女' },
{ id: 3, name: 'Charlie', age: 35, occupation: 'Teacher', sex: '男' },
{ id: 4, name: 'David', age: 40, occupation: 'Lawyer', sex: '男' },
{ id: 5, name: 'Emily', age: 28, occupation: 'Designer', sex: '女' },
{ id: 6, name: 'Frank', age: 40, occupation: 'Developer', sex: '男' }
];
//根据单个属性分类
const groupBySingleKey = (arr, key) => {
return arr.reduce((pre, cur) => {
if (!pre[cur[key]]) {
pre[cur[key]] = [cur];
} else {
pre[cur[key]].push(cur);
}
return pre;
}, {});
};
console.log(groupBySingleKey(objectArray, 'age'));
// 生成分类key
const generateKey = (item, key1, key2) => item[key1] + '-' + item[key2];
//根据多个属性分类
const groupByMoreKey = (arr, generateKey) => {
return arr.reduce((pre, cur) => {
let key = generateKey(cur, 'age', 'sex');
if (!pre[key]) {
pre[key] = [cur];
} else {
pre[key].push(cur);
}
return pre;
}, {});
};
使用场景3==>求数组交集,并集、差集
const arr1 = [1, 2, 3, 4, 5];
const arr2 = [2, 4, 6, 8, 10];
// 交集
const getIntersection = (arr1, arr2) => {
return arr1.reduce((pre, cur) => {
arr2.includes(cur) && pre.push(cur);
return pre;
}, []);
};
console.log(getIntersection(arr1, arr2));
// 并集
const getUnionOfSets = (arr1, arr2) => {
return arr1.reduce((pre, cur) => {
!pre.includes(cur) && pre.push(cur);
return pre;
}, arr2);
};
console.log(getUnionOfSets(arr1, arr2));
// 差集
const getSetOfDifferences = (arr1, arr2) => {
const allArr = [...arr1, ...arr2];
return allArr.reduce((pre, cur) => {
((arr1.includes(cur) && !arr2.includes(cur)) || (!arr1.includes(cur) && arr2.includes(cur))) && pre.push(cur);
return pre;
}, []);
};
console.log(getSetOfDifferences(arr1, arr2));
使用场景4===>返回对象指定键值
const obj = { a: 1, b: 2, c: 3 };
const getSomeKey = (obj = {}, keys = [], type = 'include') => {
return Object.keys(obj).reduce((pre, cur) => {
type === 'include' ? keys.includes(cur) && (pre[cur] = obj[cur]) : !keys.includes(cur) && (pre[cur] = obj[cur]);
return pre;
}, {});
};
// console.log(getSomeKey(obj, ['a', 'c']));
// console.log(getSomeKey(obj, ['a', 'c'], 'exclude'));
使用场景5===>树形数据转为数组
const treeData = [
{
id: 1,
title: 'Node 1',
children: [
{ id: 2, title: 'Node 1.1' },
{ id: 3, title: 'Node 1.2' }
]
},
{
id: 4,
title: 'Node 2',
children: [
{ id: 5, title: 'Node 2.1' },
{ id: 6, title: 'Node 2.2' }
]
}
];
const treeToArray = (treeData = [], path = []) => {
return treeData.reduce((pre, cur) => {
const newPath = [...path, cur.id];
let curObj = getSomeKey(cur, ['children'], 'exclude');
curObj.path = newPath;
return pre.concat(curObj).concat(!!cur.children ? treeToArray(cur.children, newPath) : []);
}, []);
};
console.log(treeToArray(treeData));