Lodash is trying to be helpful by recursively merging subobjects
This method is like _.assign except that it recursively merges own and inherited enumerable string keyed properties of source objects into the destination object. Source properties that resolve to undefined are skipped if a destination value exists. Array and plain object properties are merged recursively. Other objects and value types are overridden by assignment. Source objects are applied from left to right. Subsequent sources overwrite property assignments of previous sources.
https://lodash.com/docs/4.17.15#merge (emphasis mine)
If you don't want this to happen, just use the standard ES6 spread operator ... or Object.assign
const object1 = {
name: 'John',
age: 23,
books: ['book1', 'book2']
};
const object2 = {
name: 'John',
age: 23,
books: ['book3'],
city: 'London'
};
object3 = {...object1, ...object2};
object4 = Object.assign({}, object1, object2);
console.log(object3);
console.log(object4);
/* make the Stack Overflow console bigger */ .as-console-wrapper { max-height: 100vh !important; }
Run code snippetEdit code snippet Hide Results Copy to answer Expand
Answer from Samathingamajig on Stack Overflowjavascript - Lodash merge two objects but replace the same key values with new object value - Stack Overflow
javascript - Lodash - How to merge two arrays of objects based on key? - Stack Overflow
Is there a benefit to using lodash.merge (or other utilities of the same feature) versus merging via object destructuring?
javascript - Merge Array of Objects by Property using Lodash - Stack Overflow
You can get the result using merge and keyBy lodash functions.
var array1 = [{id:1, name:'doc1'}, {id:2, name:'doc2'}];
var array2 = [{id:1, name:'doc1'}, {id:3, name:'doc3'}, {id:4, name:'doc4'}];
var merged = _.merge(_.keyBy(array1, 'id'), _.keyBy(array2, 'id'));
var values = _.values(merged);
console.log(values);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>
Run code snippetEdit code snippet Hide Results Copy to answer Expand
Use _.unionBy() to combine two arrays, and remove duplicates that have the same unique field (id in this case). The lodash's union methods create an array of unique values. The _.unionBy() method accepts an iteratee which is invoked for each element of each array to generate the criterion by which uniqueness is computed.
const array1 = [{id:1, name:'doc1'}, {id:2, name:'doc2'}];
const array2 = [{id:1, name:'doc1'}, {id:3, name:'doc3'}, {id:4, name:'doc4'}];
const result = _.unionBy(array1, array2, 'id');
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>
Run code snippetEdit code snippet Hide Results Copy to answer Expand
Is there some kind of edge case that lodash (or other merge utilities) takes care of that const output = {...a, ...b} doesn't? (Assuming a and b are both valid)
_.unionBy():
This method is like _.union except that it accepts iteratee which is invoked for each element of each arrays to generate the criterion by which uniqueness is computed. Result values are chosen from the first array in which the value occurs.
var original = [
{ label: 'private', value: 'private@johndoe.com' },
{ label: 'work', value: 'work@johndoe.com' }
];
var update = [
{ label: 'private', value: 'me@johndoe.com' },
{ label: 'school', value: 'schol@johndoe.com' }
];
var result = _.unionBy(update, original, "label");
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.15.0/lodash.min.js"></script>
Run code snippetEdit code snippet Hide Results Copy to answer Expand
Convert the lists to objects keyed by label, merge them by _.assign, and convert it back to an array. It will even retain order of the items on most browsers.
var original = [
{
label: 'private',
value: 'private@johndoe.com'
},
{
label: 'work',
value: 'work@johndoe.com'
}
];
var update = [
{
label: 'private',
value: 'me@johndoe.com'
},
{
label: 'school',
value: 'schol@johndoe.com'
}
];
console.log(
_.map(
_.assign(
_.mapKeys(original, v => v.label),
_.mapKeys(update, v => v.label)
)
)
);
// or remove more duplicated code using spread
console.log(
_.map(
_.assign(
...[original, update].map(
coll => _.mapKeys(coll, v => v.label)
)
)
)
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.15.0/lodash.js"></script>
Run code snippetEdit code snippet Hide Results Copy to answer Expand