
本文介绍如何使用 JavaScript 的 reduce() 配合 Map,根据多个字段(如 year 和 term)对数组中对象的数值型属性(如 worthAmountEGP)进行精准分组累加,并保持原始结构完整性。
本文介绍如何使用 javascript 的 `reduce()` 配合 `map`,根据多个字段(如 `year` 和 `term`)对数组中对象的数值型属性(如 `worthamountegp`)进行精准分组累加,并保持原始结构完整性。
在实际业务开发中(例如财务统计、学生成绩汇总、课程排期分析等),我们常需对嵌套在对象数组中的数值按多维度条件聚合——而非单一字段。题中示例要求:对 worthAmountEGP 按 year 和 term 的组合进行分组求和,同时保留这两个关键维度作为输出对象的属性。若仅用 term 或 year 单一字段作为分组键(如原代码中 acc[term]),会导致跨年数据被错误合并,失去时间维度的语义准确性。
核心思路是构造唯一复合键(composite key),将多条件映射为单个字符串标识(如 "2021---2"),再借助 Map 的高效键值存取能力完成分组归并。相比普通对象,Map 支持任意类型键、可迭代、且无原型污染风险,更适合此类动态聚合场景。
以下是推荐实现方案:
const data = [
{ "year": 2020, "term": 1, "worthAmountEGP": 0 },
{ "year": 2020, "term": 2, "worthAmountEGP": 300000 },
{ "year": 2021, "term": 1, "worthAmountEGP": 0 },
{ "year": 2021, "term": 2, "worthAmountEGP": 1000000 },
{ "year": 2021, "term": 1, "worthAmountEGP": 0 },
{ "year": 2021, "term": 2, "worthAmountEGP": 400000 },
{ "year": 2022, "term": 1, "worthAmountEGP": 0 },
{ "year": 2022, "term": 2, "worthAmountEGP": 1000000 }
];
const result = Array.from(
data.reduce((acc, obj) => {
const key = `${obj.year}---${obj.term}`;
if (!acc.has(key)) {
acc.set(key, { ...obj }); // 浅拷贝,确保不修改原对象
} else {
acc.get(key).worthAmountEGP += obj.worthAmountEGP;
}
return acc;
}, new Map()).values()
);
console.log(result);
// 输出符合预期:
// [
// { year: 2020, term: 1, worthAmountEGP: 0 },
// { year: 2020, term: 2, worthAmountEGP: 300000 },
// { year: 2021, term: 1, worthAmountEGP: 0 },
// { year: 2021, term: 2, worthAmountEGP: 1400000 },
// { year: 2022, term: 1, worthAmountEGP: 0 },
// { year: 2022, term: 2, worthAmountEGP: 1000000 }
// ]✅ 关键要点说明:
- 复合键设计:使用 --- 作为分隔符(避免年份/学期数字拼接歧义,如 202-1 vs 20-21),确保键的唯一性与可读性;
- 浅拷贝安全:首次插入时用 { ...obj } 创建新对象,防止后续修改影响原始数据;
- Map 优势:has() / get() / set() 方法语义清晰,values() 返回迭代器便于转换为数组;
- 可扩展性:如需增加更多分组条件(如 department),只需扩展键生成逻辑:`${obj.year}---${obj.term}---${obj.department}`。
⚠️ 注意事项:
- 若 worthAmountEGP 可能为 null 或非数字类型,建议在累加前做类型校验(如 Number(obj.worthAmountEGP) || 0);
- 对于超大数据集(>10万条),可考虑使用 for...of 循环替代 reduce 以减少函数调用开销;
- 若需保持原始顺序(如按年份升序、学期升序排列结果),最后可对 result 执行 sort((a, b) => a.year - b.year || a.term - b.term)。
该方法简洁、健壮且易于维护,是处理多维分组求和问题的标准实践之一。

















