Reputation: 2587
I have two Object like this and want to merge them:
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 },
};
I mean, I want to not only merge the objects, but also merge their object values' properties too if the key is duplicated.
Because just merged = { ...obj1, ...obj2 };
overwrites the properties with obj2's.
What is the easiest way to do this?
I can use ES2017 and other libraries like lodash.
Upvotes: 3
Views: 4950
Reputation: 8556
This can be easily accomplished with a combination of the neat javascript spread syntax, Array and Object prototype functions, and destructuring patterns.
[obj1,obj2].flatMap(Object.entries).reduce((o,[k,v])=>({...o,[k]:{...o[k],...v}}),{})
As simple as this!
For a very detailed explanation of how this works, refer to this extended answer to a similar question.
Upvotes: 0
Reputation: 305
Are you looking like this?
we can use this way to merge two objects.
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",
}
*/
Upvotes: 0
Reputation: 287
you can use Object.assign and and assign object properties to empty object.
var a = {books: 2};
var b = {notebooks: 1};
var c = Object.assign( {}, a, b );
console.log(c);
or
You could use merge method from Lodash library. can check here : https://www.npmjs.com/package/lodash
Upvotes: 0
Reputation: 29
I have exactly what you want. This function will traverse through each nested object and combine it with the other. I've only tested it with 5 nested levels down the tree but, theoretically, it should work for any number of nested objects as it is a recursive function.
//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));
Here is a working example of a much more complex object merging
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));
Upvotes: 1
Reputation: 50759
Since you mentioned you can use lodash you can use merge
like so:
_.merge(obj1, obj2)
to get your desired result.
See working example below:
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>
Upvotes: 1
Reputation: 37755
You can use spread operator.
Update :
if obj2 has some properties that obj1 does not have?
Initially i wrote this answer assuming the keys are indexed like 0,1 and so on
but as you mentioned in comment this is not the case than you can build a array of keys and than iterate over it as
as very concisely added in comment by @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)
Upvotes: 6