Reputation: 7941
I have two object, and I want to update the target object values from source, but only the values which exists in the target already.
const target = {
a: 1,
b: 2,
c: {
c_a: 3,
c_b: 4,
}
}
const source = {
a: 10,
c: {
c_a: 30,
c_d: 50,
},
d: 60
}
const result = assignOnlyIntersection(target, source);
JSON.stringify(result)
// {
// a: 10,
// b: 2,
// c: {
// c_a: 30,
// c_b: 4
// }
// }
Is there a good way in ES6 for this? If not, does lodash has a feature for this? If not how can it be solved in a nice way?
Upvotes: 4
Views: 727
Reputation: 3451
You can combine Array.reduce()
and Object.keys()
ES6 features to achieve this:
let target = {
a: 1,
b: 2,
c: {
c_a: 3,
c_b: 4,
}
}
let source = {
a: 10,
c: {
c_a: 30,
c_d: 50,
},
d: 60
}
const assignOnlyIntersection = (sourceObj, targetObj) => {
return Object.keys(targetObj).reduce((intersection, key) => {
intersection[key] = (typeof targetObj[key] === 'object') ? assignOnlyIntersection(sourceObj[key], targetObj[key]) : sourceObj[key] || targetObj[key];
return intersection;
}, {})
}
target = assignOnlyIntersection(source, target);
console.log(target);
Upvotes: 0
Reputation: 103
another ES6 approach
non-mutative:
const intersector = (target = {}, source = {}) => {
return Object.keys(source).reduce((acc, prop) => {
if (target.hasOwnProperty(prop)) {
if (typeof source[prop] === 'object' && source[prop] !== null) {
acc[prop] = intersector(target[prop], source[prop]);
}
else {
acc[prop] = source[prop];
}
}
return acc;
}, {});
}
mutative:
const intersector = (target = {}, source = {}) => {
return Object.keys(source).reduce((acc, prop) => {
if (target.hasOwnProperty(prop)) {
if (typeof source[prop] === 'object' && source[prop] !== null) {
acc[prop] = intersector(target[prop], source[prop]);
}
else {
acc[prop] = source[prop];
}
target[prop] = acc[prop];
}
return acc;
}, target);
};
Upvotes: 0
Reputation: 386756
You could take a recursive approach by checking for objects.
function deepAssign(target, source) {
Object.keys(source).forEach(function (k) {
var objectCount = [source, target]
.map(o => o[k])
.map(o => o && typeof o === 'object')
.map(Boolean)
.reduce((a, b) => a + b)
if (!(k in target) || objectCount === 1) {
return;
}
if (objectCount === 2) {
return deepAssign(target[k], source[k]);
}
target[k] = source[k];
});
return target;
}
var source = { a: 10, c: { c_a: 30, c_d: 50, }, d: 60 },
target = { a: 1, b: 2, c: { c_a: 3, c_b: 4, } };
console.log(deepAssign(target, source));
.as-console-wrapper { max-height: 100% !important; top: 0; }
Upvotes: 0
Reputation: 665256
A simple recursive function will do:
function assignOnlyIntersection(target, source) {
if (Object(target) !== target || Object(source) !== source)
return source;
for (const p in source)
if (p in target)
target[p] = assignOnlyIntersection(target[p], source[p]);
return target;
}
Upvotes: 3
Reputation: 18429
You need to iterate through keys of target
object, check if there is same key on source
object and if so, replace the value. You also need recursion if you find an object on the way.
Something like this could do the job:
const target = { a: 1, b: 2, c: { c_a: 3, c_b: 4 }};
const source = { a: 10, c: { c_a: 30, c_d: 50 }, d: 60 };
function assignOnlyIntersection(t, s) {
Object
.keys(s)
.filter(k => k in t)
.forEach(k => {
if (typeof t[k] === 'object') {
assignOnlyIntersection(t[k], s[k]);
} else {
t[k] = s[k];
}
});
return t;
}
const result = assignOnlyIntersection(target, source);
console.log(JSON.stringify(result));
Also note that if you want to support replacing with falsy values like 0
or ''
, you will need to check for existence with typeof t[k] !== 'undefined'
.
As @ghybs noted, if you want to also support replacing with undefined
values, you will need to check via in
operator k in t
instead.
Upvotes: 0