编辑
一、array.reduce()的使用与技巧
1.1、基本语法
array.reduce(callback(accumulator, currentValue, currentIndex, array), initialValue)
1.1.1、参数
其中callback回调函数用于处理每个数组元素,最后返回一个累加值。
- accumulator:累加器,累加回调的返回值(或提供的初始值)。
- currentValue:当前元素。
- currentIndex(可选):当前元素的索引。
- array(可选):调用 reduce 的数组。
initialValue(可选):作为累加器的起始值。如果没有提供,array 的第一个元素将用作累加器的初始值,currentValue 将从 array 的第二个元素开始。
1.1.2、提供参数与行为
- 如果提供了 initialValue,累加器将被设置为这个值,currentValue 将被设置为数组的第一个元素。
- 如果没有提供 initialValue,reduce 将从索引 1 开始遍历数组,并且数组的第一个元素将作为累加器的初始值,currentValue 将从数组的第二个元素开始。
- callback 函数被依次应用到每个数组元素上,直到所有元素都被处理完毕。
- reduce 方法最后返回累加器的最终值。
1.2、返回值
一个累加值,准确来说是一个累加器,因为不一定是返回一个数值,也可以是数组等其他数据结构,这个结构主要由initialValue决定,比如initialValue是[],那么最后的累加器就是一个数组,根据回调函数决定往数组里添加什么内容。
1.3、使用技巧
array.reduce()是用于将数组元素归纳(或“缩减”)为单个值的函数。
应用场景:数据汇总、条件筛选和映射、对象属性的扁平化、转换数据格式、聚合统计、处理树结构数据、性能优化等。
1.3.1、数据汇总
在处理数据集时,经常需要对数据进行汇总,比如求和、求平均值、求最大/最小值等。
// 在处理数据集时,经常需要对数据进行汇总,比如求和、求平均值、求最大/最小值等。 const numbers = [1, 2, 3, 4, 5]; const total = numbers.reduce((acc, val) => acc + val, 0); // 求和 const average = numbers.reduce((acc, val) => acc + val, 0) / numbers.length; // 求平均值
1.3.2、条件筛选和映射
array.reduce()是可以结合条件判断,用于创建一个新数组,其中只包含满足特定条件的元素。
// reduce() 可以结合条件判断,用于创建一个新数组,其中只包含满足特定条件的元素。 const users = [ { name: 'Alice', age: 21 }, { name: 'Bob', age: 25 }, { name: 'Charlie', age: 20 } ]; const adults = users.reduce((acc, user) => { if (user.age >= 18) acc.push(user); return acc; }, []);
1.3.3、对象属性的扁平化
将嵌套的对象结构扁平化,便于后续处理。
// 将嵌套的对象结构扁平化,便于后续处理。 const data = { a: { x: 5, y: 6 }, b: { x: 7, y: 8 } }; // 方案1、使用reduce嵌套forEach(感谢yzxerha朋友提出的建议) const flattenedData = Object.keys(data).reduce((acc, key) => { Object.keys(data[key]).forEach((subKey) => { acc[key + "." + subKey] = data[key][subKey]; }); return acc; }, {}); // 方案2、使用双层reduce嵌套,为了规避双层对象嵌套,将内层的累加起始值设置为外层累加器 // 就能实现内层键值对均累加到外层累加器中,实现双层reduce嵌套结果为单层对象的效果 const flattenedData = Object.keys(data).reduce((acc, key) => { return Object.keys(data[key]).reduce((a, k) => { a[key + "." + k] = data[key][k]; return a; }, acc); }, {}); /** * flattenedData ={ * 'a.x': 5, * 'a.y': 6, * 'b.x': 7, * 'b.y': 8 * } //
1.3.4、转换数据格式
将数据从一种格式转换到另一种格式,比如将数组转换为对象。
// 将数据从一种格式转换到另一种格式,比如将数组转换为对象。 const arrayOfKeyValuePairs = [['key1', 'value1'], ['key2', 'value2']]; const obj = arrayOfKeyValuePairs.reduce((acc, [key, value]) => { acc[key] = value; return acc; }, {});
1.3.5、聚合统计
在处理日志数据或其他需要聚合统计的场景中,array.reduce()可以用于计算不同分类下的统计数据。
// 在处理日志数据或其他需要聚合统计的场景中,reduce() 可以用于计算不同分类下的统计数据。 const salesData = [ { date: '2021-01-01', product: 'Apple', amount: 10 }, { date: '2021-01-02', product: 'Apple', amount: 5 }, { date: '2021-01-01', product: 'Banana', amount: 20 }, { date: '2021-01-01', product: 'Apple', amount: 20 }, // ... 更多数据 ]; const salesSummary = salesData.reduce((acc, sale) => { const key = sale.date + '-' + sale.product; if (!acc[key]) { acc[key] = { ...sale, total: 0 }; } acc[key].total += sale.amount; return acc; }, {}); // 以该数据为例,结果就会是 /** * { * "2021-01-01-Apple": { date: '2021-01-01', product: 'Apple', amount: 20, total: 30 }, * "2021-01-02-Apple": { date: '2021-01-02', product: 'Apple', amount: 5, total: 5 }, * "2021-01-01-Banana": { date: '2021-01-01', product: 'Banana', amount: 20, total: 20 } * // ... 更多数据,如果有的话 * } */
1.3.6、处理树结构数据
在处理树状结构的数据时,array.reduce() 可以用来递归地构建一个树形结构。
// 在处理树状结构的数据时,reduce() 可以用来递归地构建一个树形结构。 const treeData = [ { id: 1, parent: null }, { id: 2, parent: 1 }, { id: 3, parent: 1 }, { id: 4, parent: 3 }, { id: 5, parent: 3 }, { id: 6, parent: null }, // 另一个根节点 { id: 7, parent: 6 }, { id: 8, parent: 2 }, { id: 9, parent: 2 }, { id: 10, parent: 8 } ]; const buildTree = (data) => { const tree = data.reduce((acc, item) => { acc[item.id] = item; // 判断是否存在parent节点 if (item.parent) { // 如果acc[item.parent].children属性不存在,就添加一个[]值 acc[item.parent].children = acc[item.parent].children || []; // 将子节点添加到父节点中 acc[item.parent].children.push(acc[item.id]); } return acc; }, {}); return Object.values(tree).filter((node) => node.parent === null); }; const tree = buildTree(treeData); // 执行完之后,tree的值为: const tree = [ { id: 1, parent: null, children: [ { id: 2, parent: 1, children: [{ id: 8, parent: 2, children: [] }, { id: 9, parent: 2, children: [] }] }, { id: 3, parent: 1, children: [{ id: 4, parent: 3, children: [] }, { id: 5, parent: 3, children: [] }] } ] }, { id: 6, parent: null, children: [{ id: 7, parent: 6, children: [] }] } ]
1.3.7、性能优化
在某些情况下,array.reduce()可以用于优化性能,因为它允许在单一的遍历中完成复杂的操作,减少了迭代次数。
// 在某些情况下,reduce() 可以用于优化性能,因为它允许在单一的遍历中完成复杂的操作,减少了迭代次数。 // 假设有一个大型数组,需要执行一个复杂的操作 const largeArray = /* ... */; const result = largeArray.reduce((accumulator, item) => { // 执行复杂操作并更新accumulator return accumulator; }, initialValue);
二、总结
array.reduce()可以用来数据汇总、条件筛选和映射、对象属性的扁平化、转换数据格式、聚合统计、处理树结构数据、性能优化等,使用难度相对高一些,但是能大大减少代码量。
W3school传送门(我的博客更详细):JavaScript Array reduce() 方法
更多前端精彩分享请移步:各种前端问题的技巧和解决方案
博客不应该只有代码和解决方案,重点应该在于给出解决方案的同时分享思维模式,只有思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~