【问题标题】:How to merge Object values of two Objects如何合并两个对象的对象值
【发布时间】:2019-06-19 23:02:54
【问题描述】:

我有两个这样的对象,想合并它们:

const obj1 = {
  1: { foo: 1 },
  2: { bar: 2, fooBar: 3 },
  3: { fooBar: 3 },
};

const obj2 = {
  1: { foo: 1, bar: 2 },
  2: { bar: 2 },
};

const merged = someMergingMethod(obj1, obj2);

merged === {
  1: { foo: 1, bar: 2 },
  2: { bar: 2, fooBar: 3 },
  3: { fooBar: 3 },
};

我的意思是,我不仅要合并对象,还要合并它们的对象值的属性也,如果键是重复的。 因为只是 merged = { ...obj1, ...obj2 }; 用 obj2 覆盖了属性。

最简单的方法是什么?

我可以使用 ES2017 和 lodash 等其他库。

【问题讨论】:

标签: javascript object ecmascript-6 lodash


【解决方案1】:

您可以使用扩展运算符。

更新:

如果 obj2 有一些 obj1 没有的属性?

最初我写了这个答案,假设键的索引像0,1 and so on,但正如你在评论中提到的那样,情况并非如此,你可以构建一个键数组,而不是像这样迭代它

@Nick [...Object.keys(obj1), ...Object.keys(obj2)] 在评论中非常简洁地添加了

let obj1 = {1: { foo: 1 },2: { bar: 2, fooBar: 3 },3: { fooBar: 3 },};
let obj2 = {1: { foo: 1, bar: 2 },2: { bar: 2 },};

let keys = [...new Set([...Object.keys(obj1),...Object.keys(obj2)])]
let  op = {}
let merged = keys.forEach(key=>{
  op[key] = {
    ...obj1[key],
    ...obj2[key]
  }
})
console.log(op)

【讨论】:

  • 谢谢,但是如果obj2 有一些obj1 没有的属性呢? :(
  • @Taichi 不是答案的原始作者,但我认为通过将 Objects.keys(obj1).forEach 更改为 [...Object.keys(obj1), ...Object.keys(obj2)].forEach 应该可以解决问题
  • @NickParsons 这太简洁了,我正在编写一个函数来实现这一点。欢呼队友:)
  • @CodeManiac 不用担心,只是另一个想法,也许通过设置等于[...new Set([...Object.keys(obj1),...Object.keys(obj2)])]; 的键会更好地删除重复项......另外,我认为merged 应该是merged = keys.forEach() ;)
【解决方案2】:

既然你提到你可以使用 lodash 你可以像这样使用merge

_.merge(obj1, obj2)

得到你想要的结果。

请参阅下面的工作示例:

const a = {
  1: { foo: 1 },
  2: { bar: 2, fooBar: 3 },
  3: { fooBar: 3 },
},

b = {
  1: { foo: 1, bar: 2 },
  2: { bar: 2 },
  4: {foo: 1}
},

res = _.merge(a, b);
console.log(res);
<script src="https://cdn.jsdelivr.net/lodash/4.16.4/lodash.min.js"></script>

【讨论】:

    【解决方案3】:

    我有你想要的。 此函数将遍历每个嵌套对象并将其与其他对象组合。我只用树下的 5 个嵌套级别对其进行了测试,但理论上,它应该适用于任意数量的嵌套对象,因为它是一个递归函数。

    //this function is similar to object.assign but,
    //leaves the keys which are common among both bojects untouched
    function merge(object1, object2)
    {
        function combine(p, q)
        {
            for(i in q)
                if(!p.hasOwnProperty(i))
                    p[i]= q[i];
            return p;
        }
        obj1= Object.assign(combine(obj1, obj2), obj1);//for the first level 
        obj1= Object.assign(traverse(obj1, obj2), obj1);//for subsequent levels down theobjectt tree
    
    //this function traverses each nested boject and combines it with the other object
        function traverse(a, b)
        {
            if(typeof(a) === "object" && typeof(b) === "object")
                for(i in b)
                    if(typeof(a[i]) === "object" && typeof(b[i]) === "object")
                        a[i]= Object.assign(traverse(a[i], b[i]), a[i]);
                    else
                        Object.assign(combine(a, b), a);
            return a;
        }
        return obj1;
    }
    
    console.log(merge(obj1, obj2));
    

    这是一个更复杂的对象合并的工作示例

    var obj1 = {
      1: { foo: 1 },
      2: { bar: 2, fooBar: 3 },
      3: { fooBar: 3, boor:{foob: 1, foof: 8} },
      4: {continent: {
      		asia: {country: {india: {capital: "delhi"}, china: {capital: "beiging"}}},
      		europe:{country:{germany: {capital: "berlin"},france: {capital: "paris"}}}
      	},
      	vegtables: {cucumber: 2, carrot: 3, radish: 7}
      }
    };
    
    var obj2 = {
      1: { foo: 1, bar: 2 },
      2: { bar: 2 },
      3: {fooBar: 3, boor:{foob: 1, boof: 6}, boob: 9 },
      4: {continent: {
      		northamerica: {country: {mexico: {capital: "mexico city"}, canada: {capital: "ottawa"}},},
      		asia: {country: {Afghanistan : {capital: "Kabul"}}}
      	}
      },
      5: {barf: 42}
    };
    
    //this function is similar to object.assign but,
    //leaves the keys which are common among both bojects untouched
    function merge(object1, object2)
    {
    	function combine(p, q)
    	{
    		for(i in q)
    			if(!p.hasOwnProperty(i))
    				p[i]= q[i];
    		return p;
    	}
    	obj1= Object.assign(combine(obj1, obj2), obj1);//for the first level 
    	obj1= Object.assign(traverse(obj1, obj2), obj1);//for subsequent levels down the object tree
    
    //this function traverses each nested boject and combines it with the other object
    	function traverse(a, b)
    	{
    		if(typeof(a) === "object" && typeof(b) === "object")
    			for(i in b)
    				if(typeof(a[i]) === "object" && typeof(b[i]) === "object")
    					a[i]= Object.assign(traverse(a[i], b[i]), a[i]);
    				else
    			 		Object.assign(combine(a, b), a);
    		return a;
    	}
    	return obj1;
    }
    
    console.log(merge(obj1, obj2));

    【讨论】:

      【解决方案4】:

      您可以使用 Object.assign 并将对象属性分配给空对象。

      var a =  {books: 2};
      var b = {notebooks: 1};
      var c = Object.assign( {}, a, b );
      console.log(c);
      

      您可以使用 Lodash 库中的合并方法。 可以在这里查看: https://www.npmjs.com/package/lodash

      【讨论】:

        【解决方案5】:

        你是这样的吗?

        我们可以用这种方式合并两个对象。

        const person = { name: 'David Walsh', gender: 'Male' };
        const attributes = { handsomeness: 'Extreme', hair: 'Brown', eyes: 'Blue' };
        const summary = {...person, ...attributes};
        

        /*

        Object {
          "eyes": "Blue",
          "gender": "Male",
          "hair": "Brown",
          "handsomeness": "Extreme",
          "name": "David Walsh",
        }
        

        */

        【讨论】:

          猜你喜欢
          • 2013-04-08
          • 2011-01-01
          • 1970-01-01
          • 2019-10-04
          • 1970-01-01
          • 1970-01-01
          • 2017-03-23
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多