Как объединить значения объекта двух объектов - PullRequest
0 голосов
/ 26 января 2019

У меня есть два таких объекта, и я хочу их объединить:

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.

Ответы [ 4 ]

0 голосов
/ 05 мая 2019

вы можете использовать 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

0 голосов
/ 26 января 2019

Так как вы упомянули, вы можете использовать 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>
0 голосов
/ 27 января 2019

У меня есть именно то, что вы хотите . Эта функция будет проходить через каждый вложенный объект и объединять его с другим. Я тестировал его только с 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));
0 голосов
/ 26 января 2019

Вы можете использовать оператор распространения.

Обновление:

если у 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)
...