How to Concatenate Arrays with Lodash mergeWith
In JavaScript development, combining deeply nested objects often
requires combining arrays rather than overwriting their contents.
Lodash's standard _.merge method recursively merges
objects, but it overwrites array elements by their index position
instead of appending them. To achieve array concatenation during a
merge, Lodash provides _.mergeWith, which accepts a
customizer function to dictate exactly how specific data types—such as
arrays—are combined.
The Default Array Behavior
of _.merge
By default, _.merge treats arrays like indexed objects.
If the target object has an array [1, 2] and the source
object has [3], the merged result will be
[3, 2]. The value at index 0 is overwritten, while the
value at index 1 remains untouched. This behavior is usually undesirable
when working with lists, where the expected behavior is typically
appending new items to the existing array.
How _.mergeWith Works
The _.mergeWith method works identically to
_.merge, but it accepts an additional
customizer callback function as its final argument:
_.mergeWith(object, sources, [customizer])The customizer function receives several arguments:
(objValue, srcValue, key, object, source, stack).
When the customizer returns a value, _.mergeWith uses
that returned value for the merge. If the customizer returns
undefined, the method falls back to Lodash's default
recursive merge strategy. This makes handling arrays straightforward:
you only handle array types in the customizer and return
undefined for everything else.
Implementing Array Concatenation
To concatenate arrays instead of overwriting their indices, check if
the target property value is an array. If it is, combine it with the
source value using JavaScript's native
Array.prototype.concat or Lodash's
_.concat:
const _ = require('lodash');
function customizer(objValue, srcValue) {
if (_.isArray(objValue)) {
return objValue.concat(srcValue);
}
}
const object1 = {
user: 'Alice',
roles: ['admin'],
settings: { theme: 'dark' }
};
const object2 = {
roles: ['editor', 'viewer'],
settings: { notifications: true }
};
const result = _.mergeWith({}, object1, object2, customizer);
console.log(result);
// Output:
// {
// user: 'Alice',
// roles: ['admin', 'editor', 'viewer'],
// settings: { theme: 'dark', notifications: true }
// }In this example, the roles arrays are concatenated into
a single list, while the nested settings object continues
to merge normally because the customizer returns undefined
for non-array values.
Handling Duplicates and Unique Values
If the goal is to concatenate arrays while removing duplicate items,
combine the concatenation logic with _.uniq or JavaScript's
Set:
function uniqueConcatCustomizer(objValue, srcValue) {
if (_.isArray(objValue)) {
return _.uniq(objValue.concat(srcValue));
}
}
const sourceA = { tags: ['javascript', 'web'] };
const sourceB = { tags: ['web', 'backend'] };
const merged = _.mergeWith({}, sourceA, sourceB, uniqueConcatCustomizer);
console.log(merged.tags);
// Output: ['javascript', 'web', 'backend']By leveraging _.mergeWith and targeting array instances
within the customizer function, you retain Lodash's deep-merging
capabilities for objects while ensuring arrays are combined according to
your application's requirements.