如何按父级_id与子级itemId对嵌套JSON数组分组合并?
JSON数组分组与属性合并方案
需求说明
需要对JSON数组执行两级分组合并操作:
- 一级分组:按**_id**将数据分组
- 二级合并:对每组内的
items数组,按itemId合并对象,将相同itemId的属性整合到同一个对象中
原始数据
let data = [ { "_id": "013", "items": [ { "itemId": "4", "stockIn": 50, "stockOut": 0 }, { "itemId": "9", "stockIn": 100, "stockOut": 0 } ] }, { "_id": "013", "items": [ { "itemId": "3", "noFreeQtyCount": 20, "freeQtyCount": 0 }, { "itemId": "9", "noFreeQtyCount": 30, "freeQtyCount": 0 } ] } ];
期望输出
[ { "_id": "013", "items": [ { "itemId": "3", "noFreeQtyCount": 20, "freeQtyCount": 0 }, { "itemId": "4", "stockIn": 50, "stockOut": 0 }, { "itemId": "9", "stockIn": 100, "stockOut": 0, "noFreeQtyCount": 30, "freeQtyCount": 0 } ] } ]
当前代码(未完成二级合并)
const groupBy = data.reduce((acc, cur) => { acc[cur._id] ? acc[cur._id].items = [...acc[cur._id].items, ...cur.items] : acc[cur._id] = cur; return acc; }, {}); const output = groupBy; print(output);
修正后的代码
// 一级分组:按_id聚合所有items const groupedById = data.reduce((acc, current) => { if (!acc[current._id]) { acc[current._id] = { _id: current._id, items: [] }; } // 将当前项的items合并到分组的items数组中 acc[current._id].items.push(...current.items); return acc; }, {}); // 二级合并:对每个分组的items按itemId整合属性 const result = Object.values(groupedById).map(group => { const mergedItems = group.items.reduce((itemAcc, item) => { // 用itemId作为key,合并属性(后面的属性会覆盖前面同名属性,这里需求是整合不同属性,所以不影响) itemAcc[item.itemId] = { ...itemAcc[item.itemId], ...item }; return itemAcc; }, {}); // 将合并后的对象转为数组 return { ...group, items: Object.values(mergedItems) }; }); console.log(result);
代码说明
- 一级分组:通过
reduce遍历原始数据,以_id为键创建分组,将所有同_id的items收集到同一个数组中。 - 二级合并:对每个分组的
items再次使用reduce,以itemId为键合并对象属性,用展开运算符...整合不同属性,最后将合并后的对象转为数组。 - 最终通过
Object.values将分组对象转为数组,得到期望的输出结构。
内容的提问来源于stack exchange,提问作者phan chanra
相关产品推荐
相关产品推荐

