JavaScript array unique: Set, filter, reduce, Map, and NaN pitfalls

Tech reviewed: Deepak Prasad
JavaScript array unique: Set, filter, reduce, Map, and NaN pitfalls

A javascript array unique (or js unique array) result removes duplicate entries while usually keeping first-seen order. The standard one-liner is [...new Set(arr)]. For javascript array distinct / distinct array javascript with objects, you either rely on reference identity in a Set, or use a Map keyed by a field. For background on Set itself, see HashSet in JavaScript (Set); for removing a known element from a list (different problem), see remove element from array in JavaScript.

Tested on: all examples in this tutorial were run with Node.js v20.18.2, and the output shown below each snippet is its exact console output.


Quick reference

Use this table for array unique javascript approaches: default primitive dedupe, NaN-safe behavior, object keys, and typical cost.

Approach Typical complexity Notes
[...new Set(arr)] O(n) Best default for primitives; handles NaN once
filter + indexOf O(n²) Fails for NaN as written
reduce + includes O(n²) Clear, fine for small arrays
Map by key O(n) Unique by property, not by reference

Set + spread — array unique javascript

Set removes duplicates using SameValueZero equality and preserves insertion order when iterated.

javascript
const arr = [1, 2, 2, 3, 3, 4, 5];
const uniqueArr = [...new Set(arr)];
console.log(uniqueArr);
text
[ 1, 2, 3, 4, 5 ]

Same result with Array.from (handy if you prefer a factory style):

javascript
console.log(Array.from(new Set([1, 2, 2])));
text
[ 1, 2 ]

The spread operator expands the Set iterator into a new array; see also creating numeric ranges as arrays when building inputs.


filter + indexOf — keep first occurrence (js array unique)

Keep the first index where indexOf still points at the current element; later duplicates fail the equality check.

javascript
const arr = [45, 67, 67, 89, 67, 69];
const uniqueArr = arr.filter((element, index, self) => {
  return index === self.indexOf(element);
});
console.log(uniqueArr);
text
[ 45, 67, 89, 69 ]

Caveat: this pattern does not work for NaN, because indexOf(NaN) is always -1:

javascript
console.log([...new Set([NaN, NaN, NaN])]);
const a = [NaN, NaN];
console.log(a.filter((e, i, s) => i === s.indexOf(e)));
text
[ NaN ]
[]

For NaN, prefer Set or something like findIndex((x) => Object.is(x, e)).


reduce + includes

Build an accumulator array and skip values already present—simple to read but includes scans the accumulator each time.

javascript
const arr = [45, 67, 67, 89, 34, 34, 69];
const uniqueArr = arr.reduce((acc, each) => {
  if (!acc.includes(each)) {
    acc.push(each);
  }
  return acc;
}, []);

console.log(uniqueArr);
text
[ 45, 67, 89, 34, 69 ]

Still O(n²) worst case because includes scans the accumulator.


for loop + includes

Imperative style matches the reduce pattern: push only when the running list does not already contain the value.

javascript
const myArray = [1, 2, 3, 2, 4, 1, 5];
const uniqueArray = [];
for (let i = 0; i < myArray.length; i++) {
  if (!uniqueArray.includes(myArray[i])) {
    uniqueArray.push(myArray[i]);
  }
}
console.log(uniqueArray);
text
[ 1, 2, 3, 4, 5 ]

See JavaScript for loop with index for loop basics.


Distinct by a key — javascript array distinct for objects

Set treats object literals as distinct references. To collapse by id, use a Map (last occurrence wins here):

javascript
const objs = [{ id: 1 }, { id: 1 }, { id: 2 }];
console.log([...new Map(objs.map((o) => [o.id, o])).values()]);
text
[ { id: 1 }, { id: 2 } ]

Summary

  • Prefer [...new Set(arr)] or Array.from(new Set(arr)) for primitive dedupe with first-seen order.
  • Avoid indexOf-based uniqueness for values that include NaN; Set handles SameValueZero correctly.
  • reduce/for + includes is readable but quadratic; fine for small inputs.
  • For objects, dedupe by a stable key with Map, not reference identity in a Set.

References

MDN references for Set, Map, and array iteration helpers used in javascript unique array recipes.


Frequently Asked Questions

1. What is the easiest way to get a javascript array unique list?

Spread a Set: const unique = [...new Set(arr)]. Set removes duplicates using SameValueZero equality and preserves insertion order when you iterate it.

2. js array unique while keeping the first occurrence of each value?

Set iteration follows first insertion order, so [...new Set(arr)] keeps the first time each value appeared.

3. Why does my filter with indexOf fail for NaN for javascript unique array?

Array.prototype.indexOf uses SameValue and cannot find NaN. indexOf(NaN) is always -1, so index === indexOf(e) drops every NaN. Use a Set, or findIndex with Object.is.

4. How do I get array distinct javascript behavior for objects by an id field?

Use a Map keyed by the field, then take .values(). Duplicate keys overwrite earlier entries—decide if you want first or last wins.

5. Array unique javascript with Set—does it deep-duplicate objects?

No. Set stores references; two different object literals are always distinct. To treat objects as equal by a key, use Map or a serialized key strategy.

6. Is filter plus indexOf slower than Set for large arrays?

Usually yes. filter with indexOf is roughly O(n squared) because indexOf scans up to i each time. Set-based dedupe is amortized O(n).
Olorunfemi Akinlua

Boasting over five years of experience in JavaScript, specializing in technical content writing and UX design. With a keen focus on programming languages, he crafts compelling content and designs user-friendly interfaces to enhance digital …

  • JavaScript
  • Web Design