Lodash intersectionWith with Custom Comparator
Lodash's _.intersectionWith method computes the
intersection of multiple arrays based on a custom comparison logic
rather than standard identity comparison. This article explains the
syntax of _.intersectionWith, describes how to construct a
custom comparator function, and provides clear, practical examples
demonstrating how to match arrays containing complex objects or
case-insensitive data.
Syntax and Parameters
The syntax for _.intersectionWith is as follows:
_.intersectionWith([arrays], [comparator])[arrays](...Array): The arrays to inspect.[comparator](Function): The comparator function invoked per element to determine equality. It accepts two arguments(arrVal, othVal)and must returntrueif the items should be treated as equal, orfalseotherwise.
Creating and Passing a Custom Comparator
A custom comparator function receives an item from the first array
(arrVal) and an item from the subsequent array
(othVal). When the comparator returns true,
the matching element from the first array is included in the output.
Example 1: Comparing Objects by Property
When working with arrays of objects, you often need to find
intersections based on a single identifier, such as an id
or sku:
const _ = require('lodash');
const listA = [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' },
{ id: 3, name: 'Charlie' }
];
const listB = [
{ id: 2, name: 'Robert' },
{ id: 4, name: 'David' }
];
// Custom comparator comparing elements by the 'id' field
const customComparator = (itemA, itemB) => itemA.id === itemB.id;
const result = _.intersectionWith(listA, listB, customComparator);
console.log(result);
// Output: [ { id: 2, name: 'Bob' } ]Notice that the resulting array retains the element from the first
array (listA).
Example 2: Deep
Object Comparison with _.isEqual
If you need to verify that nested objects match completely rather
than checking a single property, you can pass Lodash's
_.isEqual directly as the comparator:
const _ = require('lodash');
const objectsA = [
{ user: { id: 1, role: 'admin' } },
{ user: { id: 2, role: 'editor' } }
];
const objectsB = [
{ user: { id: 1, role: 'admin' } },
{ user: { id: 3, role: 'viewer' } }
];
const matchedObjects = _.intersectionWith(objectsA, objectsB, _.isEqual);
console.log(matchedObjects);
// Output: [ { user: { id: 1, role: 'admin' } } ]Example 3: Case-Insensitive String Comparison
Custom comparators can also handle string normalization, such as ignoring letter casing:
const _ = require('lodash');
const letters1 = ['apple', 'BANANA', 'Orange'];
const letters2 = ['Apple', 'banana', 'GRAPE'];
const caseInsensitiveComparator = (a, b) =>
a.toLowerCase() === b.toLowerCase();
const commonItems = _.intersectionWith(letters1, letters2, caseInsensitiveComparator);
console.log(commonItems);
// Output: [ 'apple', 'BANANA' ]Key Considerations
- Return Type: The comparator must return a strict
boolean (
trueorfalse). Non-boolean truthy/falsy values may lead to unexpected results. - Output Reference: The returned array contains references to the elements found in the first array supplied to the method.
- Multiple Arrays:
_.intersectionWithaccepts more than two arrays. The comparator is always passed as the final argument.