如何更优雅地按对象属性将数组转换为嵌套数组结构?
更优的数组嵌套转换实现方案
需求回顾
需要将包含不同level的对象数组,转换为以level=1元素为主体、嵌套对应code的level=2元素的结构,期望输出如下:
const desireOutput = [ { seq: 0, level: 1, code: '20', value: 'lorem', connectedByCode: [] }, { seq: 2, level: 1, code: '30A', value: 'lorem', connectedByCode: [ { seq: 3, level: 2, code: '30A', value: 'lorem' }, { seq: 4, level: 2, code: '30A', value: 'lorem' }, { seq: 5, level: 2, code: '30A', value: 'lorem' }] }, { seq: 8, level: 1, code: '40', value: 'lorem', connectedByCode: [] }, { seq: 13, level: 1, code: '50', value: 'lorem', connectedByCode: [] }, { seq: 15, level: 1, code: '60', value: 'lorem', connectedByCode: [] }, ];
现有代码的问题
你当前的实现虽能完成功能,但存在明显效率浪费:
level2.forEach循环中,每次都调用level2.filter,会重复生成相同的数组(比如code='30A'的元素会被过滤3次)- 每次调用
findIndex都会遍历newTable查找对应元素,数据量大时会增加不必要的开销
优化实现方案
我们可以先对level=2的元素按code分组存入Map,后续查找对应分组仅需O(1)时间,整体仅需两次遍历即可完成转换:
const array1 = [{ seq: 0, level: 1, code: '20', value: 'lorem' }, { seq: 2, level: 1, code: '30A', value: 'lorem' }, { seq: 3, level: 2, code: '30A', value: 'lorem' }, { seq: 4, level: 2, code: '30A', value: 'lorem' }, { seq: 5, level: 2, code: '30A', value: 'lorem' }, { seq: 8, level: 1, code: '40', value: 'lorem' }, { seq: 13, level: 1, code: '50', value: 'lorem' }, { seq: 15, level: 1, code: '60', value: 'lorem' }, ]; // 第一步:将level=2的元素按code分组,存入Map const level2Groups = new Map(); array1.forEach(item => { if (item.level === 2) { if (!level2Groups.has(item.code)) { level2Groups.set(item.code, []); } level2Groups.get(item.code).push(item); } }); // 第二步:处理level=1的元素,添加对应的connectedByCode const desireOutput = array1 .filter(item => item.level === 1) .map(item => ({ ...item, connectedByCode: level2Groups.get(item.code) || [] })); console.log(desireOutput);
优化点说明
- 时间效率提升:从原来的O(n*m)(n为level2元素数量,m为level1元素数量)降到O(n),仅需遍历原始数组两次
- 避免重复计算:分组操作仅执行一次,后续直接从Map中获取对应数组,无重复过滤行为
- 代码更简洁:逻辑清晰,步骤明确,可读性更强
内容的提问来源于stack exchange,提问作者freya
相关产品推荐
相关产品推荐

