使用Lodash合并嵌套对象:按id和sndid分组结构化数据
解决嵌套对象按id和sndid分组合并的问题
你之前的代码之所以只得到最后一个对象,核心原因是每次循环都把当前val的属性直接覆盖到同一个全局的assignedobject上,后面的对象会把前面的属性全部冲掉,自然只剩最后一个结果。咱们换个思路:先按id和sndid作为唯一标识分组,再把同一组内的所有零散属性合并到一个对象里。
实现步骤
- 先把所有嵌套的数组彻底扁平化,把藏在深层的单个对象都取出来
- 用
id+sndid组合成唯一键(比如${id}-${sndid}),作为分组的依据 - 对每个分组里的对象进行属性合并,把所有零散的字段整合到一个对象中
具体代码实现
这里用Lodash的几个工具函数就能轻松搞定,代码可读性也高:
const result = { '1': { 'a': [ { id: '1', sndid: 'a', type: 'ios', value: '55', weight: 2 }, { id: '1', sndid: 'a', sumvalue: 2 }, { id: '1', sndid: 'a'}, { id: '1', sndid: 'a', calcsum: '3' } ], '2': [ { id: '1', sndid: 'b', type: 'ios', value: '55', weight: 3 }, { id: '1', sndid: 'b', sumvalue: 3 }, { id: '1', sndid: 'b'}, { id: '1', sndid: 'b', calcsum: '7' } ] }, '3': { 'a': [ { id: '3', sndid: 'a', type: 'ios', value: '55', weight: 23}, { id: '3', sndid: 'a', sumvalue: 4 }, { id: '3', sndid: 'a', sumvalue_old: '4' }, { id: '3', sndid: 'a', calcsum: '5' } ] } }; // 第一步:把所有嵌套的对象数组扁平化,得到所有单个对象的集合 const allItems = _.flatMapDeep(result, (obj) => _.flatMap(obj)); // 第二步:按id和sndid的组合键分组 const groupedItems = _.groupBy(allItems, item => `${item.id}-${item.sndid}`); // 第三步:合并每组内的所有对象,把相同分组的属性整合到一起 const mergedObjects = Object.values(groupedItems).map(group => _.merge({}, ...group)); console.log(mergedObjects);
运行结果
执行后你会得到符合预期的合并数组,每个对象都包含对应id和sndid的所有属性:
[ { id: '1', sndid: 'a', type: 'ios', value: '55', weight: 2, sumvalue: 2, calcsum: '3' }, { id: '1', sndid: 'b', type: 'ios', value: '55', weight: 3, sumvalue: 3, calcsum: '7' }, { id: '3', sndid: 'a', type: 'ios', value: '55', weight: 23, sumvalue: 4, sumvalue_old: '4', calcsum: '5' } ]
补充说明
如果需要对某些属性做计算(比如你期望结果里的values、sumvalue求和),可以在合并后或者合并过程中加上对应的逻辑。比如要把sumvalue累加的话,可以把_.merge换成自定义的合并函数:
const mergedObjects = Object.values(groupedItems).map(group => { return group.reduce((acc, curr) => { // 对sumvalue做累加 if (curr.sumvalue) { acc.sumvalue = (acc.sumvalue || 0) + curr.sumvalue; } // 其他属性直接赋值(如果不存在的话) return {...acc, ...curr}; }, {}); });
这样就能根据需求灵活处理属性的计算逻辑了。
内容的提问来源于stack exchange,提问作者Ckappo
相关产品推荐
相关产品推荐

