array.reduce(callback(accumulator, currentValue, currentIndex, array), initialValue)
其中callback回调函数用于处理每个数组元素,最后返回一个累加值。
initialValue(可选):作为累加器的起始值。如果没有提供,array 的第一个元素将用作累加器的初始值,currentValue 将从 array 的第二个元素开始。
一个累加值,准确来说是一个累加器,因为不一定是返回一个数值,也可以是数组等其他数据结构,这个结构主要由initialValue决定,比如initialValue是[],那么最后的累加器就是一个数组,根据回调函数决定往数组里添加什么内容。
array.reduce()是用于将数组元素归纳(或“缩减”)为单个值的函数。
应用场景:数据汇总、条件筛选和映射、对象属性的扁平化、转换数据格式、聚合统计、处理树结构数据、性能优化等。
在处理数据集时,经常需要对数据进行汇总,比如求和、求平均值、求最大/最小值等。
// 在处理数据集时,经常需要对数据进行汇总,比如求和、求平均值、求最大/最小值等。
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; // 求平均值
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;
}, []);
将嵌套的对象结构扁平化,便于后续处理。
// 将嵌套的对象结构扁平化,便于后续处理。
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
* }
//
将数据从一种格式转换到另一种格式,比如将数组转换为对象。
// 将数据从一种格式转换到另一种格式,比如将数组转换为对象。
const arrayOfKeyValuePairs = [['key1', 'value1'], ['key2', 'value2']];
const obj = arrayOfKeyValuePairs.reduce((acc, [key, value]) => {
acc[key] = value;
return acc;
}, {});
在处理日志数据或其他需要聚合统计的场景中,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 }
* // ... 更多数据,如果有的话
* }
*/
在处理树状结构的数据时,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: [] }]
}
]
在某些情况下,array.reduce()可以用于优化性能,因为它允许在单一的遍历中完成复杂的操作,减少了迭代次数。
// 在某些情况下,reduce() 可以用于优化性能,因为它允许在单一的遍历中完成复杂的操作,减少了迭代次数。
// 假设有一个大型数组,需要执行一个复杂的操作
const largeArray = /* ... */;
const result = largeArray.reduce((accumulator, item) => {
// 执行复杂操作并更新accumulator
return accumulator;
}, initialValue);
array.reduce()可以用来数据汇总、条件筛选和映射、对象属性的扁平化、转换数据格式、聚合统计、处理树结构数据、性能优化等,使用难度相对高一些,但是能大大减少代码量。
W3school传送门(我的博客更详细):JavaScript Array reduce() 方法
更多前端精彩分享请移步:各种前端问题的技巧和解决方案
博客不应该只有代码和解决方案,重点应该在于给出解决方案的同时分享思维模式,只有思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~