Lodash uniqBy: Which Duplicate Is Kept?

The Lodash _.uniqBy method is widely used in JavaScript to remove duplicate entries from an array based on a specific iteratee function or object property. When duplicates exist, developers often need to know which version of the item remains in the final output. This article explains the selection mechanism of _.uniqBy, demonstrates its behavior with code, and outlines how to retain the last duplicate instead of the default choice.

The Selection Rule: First Occurrence Wins

When _.uniqBy processes an array, it always preserves the first occurrence of each unique item and discards all subsequent duplicates.

The method traverses the array sequentially from left to right (from index 0 to array.length - 1). For each element, it executes the provided iteratee (a property name, function, or path) to compute a comparison key. If that computed key has not been seen before, the item is added to the result array. If the key has already been encountered, the current item is skipped.

Code Example

Consider an array of user objects where two entries share the same id:

const _ = require('lodash');

const users = [
  { id: 1, name: 'Alice', status: 'pending' },
  { id: 2, name: 'Bob', status: 'active' },
  { id: 1, name: 'Alice', status: 'approved' }
];

const result = _.uniqBy(users, 'id');

console.log(result);

Output:

[
  { id: 1, name: 'Alice', status: 'pending' },
  { id: 2, name: 'Bob', status: 'active' }
]

In this example, the item with status: 'pending' is kept because it appears first in the array. The second item with id: 1 and status: 'approved' is discarded.

How to Keep the Last Occurrence Instead

Because _.uniqBy natively keeps only the first item, you must alter the order of traversal if your application requires keeping the latest or last occurrence.

The most common approach is to reverse a shallow copy of the array before passing it to _.uniqBy, and optionally reverse the result back to maintain the original relative sequence:

const _ = require('lodash');

const users = [
  { id: 1, name: 'Alice', status: 'pending' },
  { id: 2, name: 'Bob', status: 'active' },
  { id: 1, name: 'Alice', status: 'approved' }
];

// Keep the last occurrence
const result = _.uniqBy([...users].reverse(), 'id').reverse();

console.log(result);

Output:

[
  { id: 2, name: 'Bob', status: 'active' },
  { id: 1, name: 'Alice', status: 'approved' }
]

Summary