首页 > 解决方案 > 将 2 个嵌套对象组合在一起,同时保留两者的属性,同时将重复的键值添加在一起

问题描述

我看过几篇关于将两个对象合并在一起的帖子,但其中大多数是用于合并包含不包含嵌套元素的对象的对象。当我实施建议的解决方案之一时,一个对象的属性将被覆盖。

const Gnome = () => {
  return {
    ExpRate: .20,
    Abilities: {
      PickDoors: 1,
    },
    Buffs: {
      NightSight: 65, 
      MagicRes: 5, 
    },
    ... Additional data and behaviors
  };
}

const Thief = () {
  return {
    ExpRate: 2.10, 
    Abilities: {
      Thievery: 1,
      PickDoors: 1, 
    },
    Buffs: {}, 
    // ... Additional data and behavors
  };
}

我一直在尝试将这两个对象合并为:

{
 ExpRate: 2.30,
 Abilities: {
    PickDoors: 2,
    Thievery: 1
 }, 
 Buffs: {
    NightSight: 65,
    MagicRes: 5, 
 }, 
// ... Additional data and behavors from both objects
};

但是,使用 Object.assign 会覆盖现有键中的值,从而丢失数据。IE:

const myGnome = Gnome();
const myThief = Thief();
const myPlayer = Object.assign({}, myGnome, myThief);

我已经尝试了人们发布的一些建议的合并方法,但它们似乎都具有与 Object.assign(); 相同的行为;任何建议,将不胜感激。如果这实际上是重复的帖子,我会喜欢它的链接。

提前致谢。

标签: javascript

解决方案


您可以迭代条目并检查是否找到对象,然后再次为嵌套对象调用该函数。如果找到数字,则添加此值。

function merge(a, b) {
    function mergeTo(source, target) {
        Object.entries(source).forEach(([k, v]) => {
            if (Array.isArray(v)) {
                target[k] = target[k] || [];
                target[k].push(...v);
                return;
            }
            if (v && typeof v === 'object') {
                mergeTo(v, target[k] = target[k] || {});
                return;
            }
            if (typeof v === 'number') { 
                target[k] = (target[k] || 0) + v;
                return;
            }
            if (!(k in target)) {
                target[k] = v;
                return;
            }
            target[k] = Array.isArray(target[k])
                ? [...target[k], v]
                : [target[k], v];
        });
    }

    var object = {};
    mergeTo(a, object);
    mergeTo(b, object);
    return object;
}

console.log(merge(
    { ExpRate: .20, Abilities: { PickDoors: 1 }, Buffs: { NightSight: 65, MagicRes: 5 }, array: [1, 2], v: 'a' },
    { ExpRate: 2.10, Abilities: { Thievery: 1, PickDoors: 1 }, Buffs: {}, array: [3, 4], v: 'b', f: true }
));
.as-console-wrapper { max-height: 100% !important; top: 0; }


推荐阅读