You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

递归合并不同层级同键JSON数组 如何用map实现全节点匹配

嵌套JSON数组属性合并实现

需求说明

需要合并两个JSON数组生成最终结构:

  • 基础数组r1为多层嵌套树结构,子节点存储在sub_items字段中
  • 数组r2存储待追加的扩展属性,通过唯一标识item_guid和r1中的节点匹配,将r2节点的属性合并到对应r1节点上
  • 合并需要支持任意深度的嵌套子节点,不能仅处理第一层子项

原始r1结构

const r1=[{
    "item_guid": "5c2000c1-abc8-4d6f-85de-b8b223a42a2f",
    "item_id": 1,
    "parent_item_id": null,
    "description": "1",
    "sub_items": [
        {
            "item_guid": "bd7c2ba3-268b-49f6-98fb-34486a3e1449",
            "item_id": 10,
            "parent_item_id": 1,
            "description": "1.1",
            "sub_items": []
        },
        {
            "item_guid": "80e073e0-2aa8-422a-9f28-51747f146bd8",
            "item_id": 12,
            "parent_item_id": 1,
            "description": "1.2",
            "sub_items": [
                {
                    "item_guid": "f97af55c-c90e-46c2-b56e-e854ff36e1e3",
                    "item_id": 78,
                    "parent_item_id": 12,
                    "description": "1.2.1",
                    "sub_items": []
                },
                {
                    "item_guid": "28469fa4-2c1c-4f2a-9250-7460a74cc30a",
                    "item_id": 79,
                    "parent_item_id": 12,
                    "description": "1.2.2",
                    "sub_items": [
                        {
                            "item_guid": "f97af55c-c90e-46c2-b56e-e854ff36e1e9",
                            "item_id": 80,
                            "parent_item_id": 12,
                            "description": "1.2.2.1",
                            "sub_items": []
                        },
                    ]
                }
            ],
        },
        {
            "item_guid": "846daeab-edd4-4cf2-8f12-8d7231c697e3",
            "item_id": 13,
            "parent_item_id": 1,
            "description": "1.3",
            "sub_items": [],
        },
    ],
}]

原始r2结构

const r2=[
{
    "item_guid": "bd7c2ba3-268b-49f6-98fb-34486a3e1449",
    "mandatory": "True",
    "comment": "Item cross-reference 1.1"
},
{
    "item_guid": "f97af55c-c90e-46c2-b56e-e854ff36e1e3",
    "mandatory": "True",
    "comment": "Item cross-reference 1.2.1"
},
{
    "item_guid": "f97af55c-c90e-46c2-b56e-e854ff36e1e9",
    "mandatory": "True",
    "comment": "Item cross-reference 1.2.2.1"
}]

预期合并结果

合并后所有匹配到item_guid的节点都追加mandatory和comment属性,不匹配的节点保持原有结构不变。

现有代码问题

原有实现仅手动处理了第一层sub_items,没有递归遍历更深层级,同时直接修改了原数组对象会产生副作用,代码如下:

const mergeById = (r1, r2) =>
r1.map(itm => {
 itm.sub_items = itm.sub_items.map(sub_item => (
     { ...sub_item,
       ...r2.find(r2_item => r2_item.item_guid === sub_item.item_guid),
     }
    )
    )
  
   return itm 
})

console.log(mergeById(r1,r2))

实现方案

完全可以基于map方法配合递归实现任意层级的合并,核心逻辑是封装递归处理函数,每处理一个节点时,先合并匹配的扩展属性,再递归处理当前节点的sub_items数组。
为了提升查询性能,先把r2转换成item_guid为键的映射表,避免每层循环都用find遍历r2:

const mergeItems = (baseList, extList) => {
  // 构建扩展属性映射表,查询时间复杂度从O(n)降到O(1)
  const extMap = Object.fromEntries(extList.map(item => [item.item_guid, item]));

  // 递归处理节点列表
  const processNodeList = (list) => {
    return list.map(node => {
      // 合并当前节点的基础属性和匹配到的扩展属性
      const mergedNode = {
        ...node,
        ...(extMap[node.item_guid] || {})
      };
      // 存在子节点时递归处理
      if (Array.isArray(node.sub_items) && node.sub_items.length) {
        mergedNode.sub_items = processNodeList(node.sub_items);
      }
      return mergedNode;
    })
  }

  return processNodeList(baseList);
}

// 调用获取结果
const r3 = mergeItems(r1, r2);
console.log(r3);

方案说明

  • 全程使用map方法遍历,符合预期的实现方式
  • 支持任意深度的sub_items嵌套,不存在层级限制
  • 所有节点都返回新对象副本,不会修改原始的r1、r2数组,无副作用
  • 映射表的实现比循环find性能更高,数据量大时优势明显

内容的提问来源于stack exchange,提问作者JarochoEngineer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.03 01:57:26