如何按指定属性分组合并数组对象以生成新数组项?
数组分组转换实现方案
问题描述
现有如下对象数组:
rows = [ { id_temp: 1, description: 'template 1', color_id: 1, code: '#000000' }, { id_temp: 1, description: 'template 1', color_id: 2, code: '#ffffff' }, { id_temp: 2, description: 'template 2', color_id: 1, code: '#000000' }, { id_temp: 2, description: 'template 2', color_id: 2, code: '#ffffff' }, ]
需要将其转换为按id_temp分组的结构,新增color数组属性,包含对应color_id(作为id)和code:
[{ "id_temp": 1, "description": "template 1", "color": [{ "id": 1, "code": "#000000" }, { "id": 2, "code": "#ffffff" }] }, { "id_temp": 2, "description": "template 2", "color": [{ "id": 1, "code": "#000000" }, { "id": 2, "code": "#ffffff" }] }]
尝试用forEach循环处理时出现值被覆盖的问题,错误代码如下:
let resultTemplates = []; rows.forEach((row) => { if (resultTemplates[row.id_temp]) { resultTemplates['color'] = row.color_id; resultTemplates['color'] = row.code; } else { resultTemplates.id_temp = row.id_temp; resultTemplates.description = row.description; resultTemplates['color'].id = row.color_id; resultTemplates['color'].code = row.code; } });
错误原因分析
你的代码存在几个关键问题:
resultTemplates是数组,但你直接给它设置id_temp、description等属性,违背了数组的使用逻辑——数组应该存储对象元素,而非将数组本身当作对象赋值。- 判断
resultTemplates[row.id_temp]时,数组索引从0开始,但id_temp是1、2,初始时resultTemplates[1]不存在,会进入else分支,此时resultTemplates['color']未初始化就直接赋值id和code,会触发报错。 - 即使进入if分支,你直接给
resultTemplates['color']赋值,会覆盖之前的数据,而非向数组中添加新元素。
正确实现方法
方法一:forEach+对象映射(性能更优)
通过临时对象按id_temp分组存储数据,最后将对象值转为目标数组:
const tempMap = {}; rows.forEach(row => { // 检查当前id_temp是否已在映射中 if (!tempMap[row.id_temp]) { // 初始化分组对象 tempMap[row.id_temp] = { id_temp: row.id_temp, description: row.description, color: [] }; } // 往color数组中添加当前颜色项 tempMap[row.id_temp].color.push({ id: row.color_id, code: row.code }); }); // 把映射对象的值转为目标数组 const resultTemplates = Object.values(tempMap); console.log(resultTemplates);
方法二:reduce(写法更简洁)
利用Array.reduce一步完成分组和转换:
const resultTemplates = rows.reduce((acc, row) => { // 查找当前id_temp对应的分组对象 const existing = acc.find(item => item.id_temp === row.id_temp); if (existing) { // 已存在则添加颜色项 existing.color.push({ id: row.color_id, code: row.code }); } else { // 不存在则新增分组对象 acc.push({ id_temp: row.id_temp, description: row.description, color: [{ id: row.color_id, code: row.code }] }); } return acc; }, []); console.log(resultTemplates);
两种方法都能得到目标结构,其中方法一为O(n)时间复杂度,数据量较大时推荐使用;方法二写法更简洁,适合数据量较小的场景。
内容的提问来源于stack exchange,提问作者Ali Almazawi
相关产品推荐
相关产品推荐

