How to Use Lodash unionWith with a Comparator
Lodash's _.unionWith creates a single array of unique
values in order from multiple provided arrays, using a custom comparator
function instead of standard strict equality to identify duplicates.
This article covers how _.unionWith passes elements to the
comparator, how return values dictate uniqueness, and practical
implementations for merging complex data structures such as objects.
Understanding the Syntax
The syntax for _.unionWith accepts any number of arrays
followed by the comparator function as the final argument:
_.unionWith([...arrays], [comparator])...arrays: The arrays to inspect.comparator: The function invoked per comparison to compare elements (arrVal,othVal).
How the Comparator Works
Standard union operations in JavaScript typically rely on
SameValueZero or strict equality (===), which
fails when comparing complex reference types like objects because two
distinct objects with identical properties are evaluated as unequal.
_.unionWith solves this by iterating through the
concatenated values of all input arrays. As it constructs the result
array:
- It takes each incoming candidate element.
- It compares the candidate against every element already accepted
into the result array by calling
comparator(arrVal, othVal). - The comparator receives two arguments:
arrVal(an element already stored in the accumulator) andothVal(the incoming candidate). - If the comparator returns a truthy value,
_.unionWithconsiders the elements duplicates and discardsothVal. - If the comparator returns falsy for all existing elements,
othValis recognized as unique and pushed into the result array.
Practical Example with Objects
A common use case involves merging arrays of objects where equality is defined by deep equality or by specific business keys.
const _ = require('lodash');
const primaryUsers = [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' }
];
const secondaryUsers = [
{ id: 2, name: 'Bob' },
{ id: 3, name: 'Charlie' }
];
// Using Lodash's _.isEqual as the comparator for deep comparison
const deepUnique = _.unionWith(primaryUsers, secondaryUsers, _.isEqual);
// Using a custom comparator function based on an ID property
const customUnique = _.unionWith(primaryUsers, secondaryUsers, (a, b) => a.id === b.id);
console.log(customUnique);
// Output:
// [
// { id: 1, name: 'Alice' },
// { id: 2, name: 'Bob' },
// { id: 3, name: 'Charlie' }
// ]unionWith vs.
union and unionBy
Choosing the correct Lodash union method depends on your equality criteria:
_.union: Uses strict equality (SameValueZero). It is ideal for primitive values (numbers, strings) but unsuitable for object uniqueness._.unionBy: Accepts an iteratee (a property name or a mapping function) invoked for each element to generate a criterion key, which is then compared using standard equality. It evaluates elements individually rather than comparing them in pairs._.unionWith: Accepts a pairwise comparator(a, b)returning a boolean. It provides the highest degree of flexibility, allowing custom logic such as tolerance-based numeric comparisons, deep comparisons, or dynamic multi-field matching.