使用Lodash或原生JS实现对象数组按city分组与指定动态字段求和
问题原因分析
你的现有代码存在几个核心问题导致求和结果不符合预期:
- 未做类型转换:你拿到的
item[d]如果是数值格式的字符串/空串,直接累加会触发字符串拼接,而不是数值求和 - 空值判断有误:空串
''转数字为0,isNaN('')返回false,会导致空值被当做0参与计算 - 直接引用原对象:直接把原
itempush进结果数组,会保留不需要的字段(比如phone、04/09),还会意外修改原对象数据 - 查找效率低:每次用
find遍历数组查找分组,数据量大的时候性能会明显下降
原生JavaScript实现方案
用对象做分组映射,查找效率为O(1),是性能最优的原生实现方式:
const groupByAndSum = (data, groupKey, sumKeys) => { const groupMap = data.reduce((acc, item) => { // 这里trim是处理你示例中NewYork/New York的空格差异,不需要可删除 const groupVal = item[groupKey].trim(); // 不存在则初始化分组项 if (!acc[groupVal]) { acc[groupVal] = { [groupKey]: groupVal }; sumKeys.forEach(key => acc[groupVal][key] = ''); } // 累加指定字段 sumKeys.forEach(key => { const val = Number(item[key]); // 只有合法数值参与求和 if (!isNaN(val)) { acc[groupVal][key] = (Number(acc[groupVal][key]) || 0) + val; } }); return acc; }, {}); // 把映射对象转成结果数组 return Object.values(groupMap); }; // 调用即可得到预期结果 const result = groupByAndSum(salesData, 'city', dynamicKeys);
Lodash实现方案
借助Lodash工具函数简化写法,适合项目已经引入Lodash的场景:
const result = _.chain(salesData) .groupBy(item => item.city.trim()) // 按city分组,处理空格差异 .map((groupItems, city) => { // 对每个分组的指定字段求和 return dynamicKeys.reduce((acc, key) => { const sum = groupItems.reduce((total, item) => { const val = Number(item[key]); return total + (isNaN(val) ? 0 : val); }, 0); // 无有效求和值时返回空串,符合你的输出要求 acc[key] = sum === 0 ? '' : sum; return acc; }, { city }); }) .value();
内容的提问来源于stack exchange,提问作者Ranjith M
相关产品推荐
相关产品推荐

