Lodash difference vs differenceBy Explained
The primary difference between the _.difference and
_.differenceBy methods in Lodash lies in how they evaluate
elements for comparison. While _.difference compares array
values directly using standard equality, _.differenceBy
allows you to pass an iteratee function or property shorthand to
transform or inspect elements before the comparison takes place. This
makes _.difference ideal for primitive arrays and
_.differenceBy the go-to choice for complex data
structures, such as arrays of objects.
Understanding
_.difference
The _.difference method takes a base array and one or
more arrays of values to exclude. It returns a new array containing only
the elements from the base array that are not present in the other
arrays.
Under the hood, _.difference uses the
SameValueZero algorithm for equality comparisons, similar
to ===. Because it compares values directly by identity, it
works effectively with primitive data types such as strings, numbers,
and booleans.
const _ = require('lodash');
const numbers = [2, 1, 5, 3];
const toExclude = [2, 3];
const result = _.difference(numbers, toExclude);
// Output: [1, 5]However, _.difference fails when dealing with
non-primitive types like objects, unless both arrays reference the exact
same object instances in memory:
const usersA = [{ id: 1 }, { id: 2 }];
const usersB = [{ id: 1 }];
// Fails because the objects have different memory references
const result = _.difference(usersA, usersB);
// Output: [{ id: 1 }, { id: 2 }]Understanding
_.differenceBy
The _.differenceBy method accepts the same arguments as
_.difference, but adds an iteratee as its
final argument. The iteratee is invoked for each element in all provided
arrays to generate the criterion by which values are compared.
The iteratee can be:
- A custom function
- A string representing an object property key
- A property path
Example with Property Names
When working with arrays of objects, you can supply a property name to filter out items sharing the same property value:
const usersA = [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }];
const usersB = [{ id: 1, name: 'Alice' }];
const result = _.differenceBy(usersA, usersB, 'id');
// Output: [{ id: 2, name: 'Bob' }]Example with a Custom Function
You can also supply a custom function to transform values prior to comparison, such as rounding numbers:
const decimalsA = [2.1, 1.2, 3.7];
const decimalsB = [2.3, 3.4];
const result = _.differenceBy(decimalsA, decimalsB, Math.floor);
// Output: [1.2]In this scenario, 2.1 and 2.3 both floor to
2, and 3.7 and 3.4 both floor to
3, leaving only 1.2.
Key Differences Summary
| Feature | _.difference |
_.differenceBy |
|---|---|---|
| Comparison Strategy | Direct comparison via
SameValueZero. |
Compares the results of an applied iteratee. |
| Iteratee Support | No iteratee support. | Accepts a function, property key, or path. |
| Best Used For | Flat arrays of primitive values. | Arrays of objects or transformed comparisons. |
| Performance | Slightly faster due to the absence of callback execution. | Carries minor overhead from invoking the iteratee. |