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])

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:

  1. It takes each incoming candidate element.
  2. It compares the candidate against every element already accepted into the result array by calling comparator(arrVal, othVal).
  3. The comparator receives two arguments: arrVal (an element already stored in the accumulator) and othVal (the incoming candidate).
  4. If the comparator returns a truthy value, _.unionWith considers the elements duplicates and discards othVal.
  5. If the comparator returns falsy for all existing elements, othVal is 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: