如何按单个属性汇总JavaScript数组并生成统计结果?
问题
参考大量示例后仍无法实现需求,当前结果会保留汇总时应剔除的属性(如period)。希望输出一个按location汇总的新数组,仅包含location、totalCountIn和totalCountOut,不保留时段等细节。推测问题出在Object.assign({}, o)这行代码——它会创建对象的完整副本,但不知道如何仅创建含location的对象来累加统计值。以下是简化示例,实际场景中需要汇总多列并剔除多列:
示例代码:
let helper = {}; let locationPeriodCounts = [ {"period": "2023-10-21", "location": "228", "countIn": 6, "countOut": 1}, {"period": "2023-10-22", "location": "228", "countIn": 8, "countOut": 2}, {"period": "2023-10-23", "location": "228", "countIn": 3, "countOut": 3}, {"period": "2023-10-24", "location": "228", "countIn": 1, "countOut": 4}, {"period": "2023-10-21", "location": "229", "countIn": 5, "countOut": 6}, {"period": "2023-10-22", "location": "229", "countIn": 18, "countOut": 6}, {"period": "2023-10-23", "location": "229", "countIn": 8, "countOut": 6}, {"period": "2023-10-24", "location": "230", "countIn": 3, "countOut": 6}, {"period": "2023-10-25", "location": "230", "countIn": 4, "countOut": 6} ]; let locationCounts = locationPeriodCounts.reduce(function(r, o) { let key = o.location; if (!helper[key]) { helper[key] = Object.assign({}, o); // create a copy of o helper[key].totalCountIn = 0; helper[key].totalCountOut = 0; r.push(helper[key]); } else { helper[key].totalCountIn += o.countIn; helper[key].totalCountOut += o.countOut; } return r; }, []); console.log(locationCounts);
期望输出:
[ {"location": "228", "totalCountIn": 18, "totalCountOut": 10}, {"location": "229", "totalCountIn": 31, "totalCountOut": 18}, {"location": "230", "totalCountIn": 7, "totalCountOut": 12} ]
解决方案
你猜的没错,问题确实出在Object.assign({}, o)——它会把原对象的所有属性(包括period)都复制过来。要解决这个问题,我们不需要复制整个原对象,而是手动构建只包含目标属性的初始对象,具体修改如下:
let helper = {}; let locationPeriodCounts = [ {"period": "2023-10-21", "location": "228", "countIn": 6, "countOut": 1}, {"period": "2023-10-22", "location": "228", "countIn": 8, "countOut": 2}, {"period": "2023-10-23", "location": "228", "countIn": 3, "countOut": 3}, {"period": "2023-10-24", "location": "228", "countIn": 1, "countOut": 4}, {"period": "2023-10-21", "location": "229", "countIn": 5, "countOut": 6}, {"period": "2023-10-22", "location": "229", "countIn": 18, "countOut": 6}, {"period": "2023-10-23", "location": "229", "countIn": 8, "countOut": 6}, {"period": "2023-10-24", "location": "230", "countIn": 3, "countOut": 6}, {"period": "2023-10-25", "location": "230", "countIn": 4, "countOut": 6} ]; let locationCounts = locationPeriodCounts.reduce(function(r, o) { let key = o.location; if (!helper[key]) { // 只初始化需要的属性,完全避免多余字段 helper[key] = { location: o.location, totalCountIn: 0, totalCountOut: 0 }; r.push(helper[key]); } // 统一放在判断外部累加,减少重复代码 helper[key].totalCountIn += o.countIn; helper[key].totalCountOut += o.countOut; return r; }, []); console.log(locationCounts);
关键优化点
- 手动构建初始对象:不再复制原对象的所有属性,只创建包含
location和统计字段的对象,从根源上避免带入period等多余属性。 - 统一累加逻辑:把累加代码移到判断外部,首次创建对象后直接累加当前的数值,无需在
else分支重复编写累加逻辑,代码更简洁。
适配多列汇总场景
如果实际需要汇总更多字段,只需要在初始对象中添加对应的统计字段,再补充累加逻辑即可:
// 示例:新增countTransfer字段的汇总 helper[key] = { location: o.location, totalCountIn: 0, totalCountOut: 0, totalCountTransfer: 0 // 新增统计字段 }; // 新增累加逻辑 helper[key].totalCountTransfer += o.countTransfer;
内容的提问来源于stack exchange,提问作者Chris
相关产品推荐
相关产品推荐

