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

JavaScript中基于ID深度合并嵌套对象的实现方案

基于ID的嵌套对象深度合并方案

针对嵌套数组需按指定ID匹配更新、避免重复的需求,以下是无需依赖lodash的自定义实现方案,核心逻辑是通过ID映射精准匹配并覆盖对象,同时保留未被更新的原有条目。

实现代码

// 按指定key合并两个数组:新对象覆盖同key旧对象,无重复条目
function mergeArraysById(oldArr, newArr, idKey = 'id') {
  const newItemMap = new Map(newArr.map(item => [item[idKey], item]));
  // 保留旧数组条目,用新数据覆盖匹配项;再加入旧数组没有的新条目
  return [
    ...oldArr.map(item => newItemMap.get(item[idKey]) || item),
    ...newArr.filter(item => !oldArr.some(oldItem => oldItem[idKey] === item[idKey]))
  ];
}

// 深度合并对象:cards数组按iid合并,子数组按id合并
function deepMergeWithId(original, update) {
  // 非对象类型直接返回更新值(若存在)
  if (typeof original !== 'object' || original === null) {
    return update !== undefined ? update : original;
  }
  if (typeof update !== 'object' || update === null) {
    return update;
  }

  const merged = { ...original };

  for (const key of Object.keys(update)) {
    const originalVal = merged[key];
    const updateVal = update[key];

    // 处理顶层cards数组,按iid匹配卡片
    if (key === 'cards') {
      const updateCardMap = new Map(updateVal.map(card => [card.iid, card]));
      merged.cards = originalVal.map(originalCard => {
        const updateCard = updateCardMap.get(originalCard.iid);
        if (!updateCard) return originalCard;

        // 合并单个卡片内容
        const mergedCard = { ...originalCard };
        // 合并sub_arr子数组
        if (updateCard.sub_arr) {
          mergedCard.sub_arr = mergeArraysById(originalCard.sub_arr || [], updateCard.sub_arr);
        }
        // 合并support子数组
        if (updateCard.support) {
          mergedCard.support = mergeArraysById(originalCard.support || [], updateCard.support);
        }
        // 覆盖卡片的其他非数组属性
        Object.keys(updateCard).forEach(cardKey => {
          if (!['sub_arr', 'support'].includes(cardKey)) {
            mergedCard[cardKey] = updateCard[cardKey];
          }
        });
        return mergedCard;
      });
      // 添加更新数据中新增的卡片(若有)
      merged.cards.push(...updateVal.filter(updateCard => !originalVal.some(oc => oc.iid === updateCard.iid)));
    } else {
      // 其他属性递归深度合并
      merged[key] = deepMergeWithId(originalVal, updateVal);
    }
  }

  return merged;
}

// 使用示例
const originalData = {
  "cards": [
    {
      "iid": 154423,
      "number": 1,
      "name": "name",
      "sub_arr": [
        { "name": "name", "id": "94184", "point": "6", "event": "cff" },
        { "name": "name", "id": "90363", "event": "cff" },
        { "name": "name", "id": "94185", "point": "3", "event": "cff" }
      ],
      "support": [
        { "name": "Richardson", "id": "43478" },
        { "name": "Jason", "id": "43582" }
      ]
    },
    {
      "iid": 154430,
      "number": 2,
      "sub_arr": [
        { "name": "name", "id": "94174", "point": "6", "event": "cff" },
        { "name": "name", "id": "90373", "event": "cff" },
        { "name": "name", "id": "94175", "point": "3", "event": "cff" }
      ],
      "support": [
        { "name": "son", "id": "43468" },
        { "name": "Jas", "id": "43552" }
      ]
    }
  ],
  "status_text": "success",
  "status_code": 200
};

const updateData = {
  "cards": [
    {
      "iid": 154423,
      "number": 1,
      "name": "name",
      "sub_arr": [
        { "name": "name", "id": "94184", "point": "6", "event": "ghd" }
      ],
      "support": [
        { "name": "dson", "id": "43478" }
      ]
    }
  ]
};

const mergedResult = deepMergeWithId(originalData, updateData);
console.log(JSON.stringify(mergedResult, null, 2));

逻辑说明

  1. mergeArraysById函数:将新数组转为ID映射表,遍历旧数组时用新数据覆盖同ID条目,同时补充旧数组没有的新条目,确保无重复。
  2. deepMergeWithId函数:
    • 针对顶层cards数组,按iid匹配对应的卡片对象;
    • 对每个卡片内的sub_arr和support子数组,调用mergeArraysById按id合并;
    • 非数组属性直接用更新数据覆盖,其他嵌套对象递归合并;
    • 支持添加更新数据中新增的卡片条目。

运行示例后,合并结果会保留原有未被更新的所有条目,仅修改iid=154423卡片中id=94184的event值为ghd、id=43478的name值为dson,无重复条目。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 21:14:58