如何按atributo中的id分组聚合对象数组并求和valor字段?
正确实现按
atributo.id分组求和的方案 你的思路方向是对的,但原reduce代码存在几个关键问题:
- 没有给
reduce设置初始值,导致第一次迭代时acc是数组的第一个元素,后续如果执行return a + Number(b.valor),acc会变成数字,再迭代时访问a.atributo.id就会直接报错(数字没有atributo属性)。 - 逻辑上没有维护多分组的存储,只能尝试处理连续的同组元素,没法同时保存多个不同
atributo.id的分组数据。
下面是完整的正确实现:
const myArr = [{id: 21852, atributo: {id: 20}, valor: "876.98"}, {id: 21853, atributo: {id:21}, valor: "760"}, {id: 21858, atributo: {id:20}, valor: "876.98"}, {id: 21859, atributo: {id:21}, valor: "760"}]; // 1. 用reduce创建分组映射,key为atributo.id,value存储分组的属性和累加值 const groupMap = myArr.reduce((acc, currentItem) => { const attrId = currentItem.atributo.id; // 如果当前分组不存在,初始化结构 if (!acc[attrId]) { acc[attrId] = { atributo: {...currentItem.atributo}, // 浅拷贝避免原对象被修改 valor: 0 }; } // 将当前item的valor转成数字后累加 acc[attrId].valor += parseFloat(currentItem.valor); return acc; }, {}); // 必须传入初始空对象,确保acc始终是对象类型 // 2. 将分组映射转成目标数组,并添加自增的id const finalResult = Object.values(groupMap).map((groupItem, index) => ({ id: index + 1, ...groupItem, // 把求和后的数字转成带逗号分隔的格式(匹配你期望的输出) valor: groupItem.valor.toFixed(2).replace('.', ',') })); console.log(finalResult); // 输出结果: // [{id: 1, atributo: {id: 20}, valor: "1753,96"}, {id: 2, atributo: {id:21}, valor: "1520,00"}]
额外说明:
- 如果你的
valor原始数据中存在逗号作为小数分隔符(比如"876,98"),需要先替换成点再转数字:parseFloat(currentItem.valor.replace(',', '.'))。 - 如果不需要保留小数位,可以把
toFixed(2)去掉,直接用groupItem.valor.toString().replace('.', ','),或者根据需求处理数字格式。
内容的提问来源于stack exchange,提问作者gwerle
相关产品推荐
相关产品推荐

