JavaScript
Array Methods
Data Structures
Programming Tips
Code Optimization

Remove duplicate objects from an array using javascript

Data Structures & Algorithms practice on Codemia

Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.

Practice algorithms

Introduction

Removing duplicate objects from a JavaScript array is not the same as removing duplicate numbers or strings. Objects are compared by reference, so two separate objects with the same properties are still considered different unless you choose a key or equality rule yourself.

Why Set Alone Does Not Solve It

A Set removes duplicate references, not duplicate shapes:

javascript
1const a = { id: 1, name: "Ada" };
2const b = { id: 1, name: "Ada" };
3
4console.log(a === b); // false
5
6const unique = [...new Set([a, b])];
7console.log(unique.length); // 2

That is the core reason duplicate-removal code for objects needs custom logic.

The Best Approach When Objects Have A Stable Key

If each object has a unique identifier such as id, use a Map keyed by that field:

javascript
1const users = [
2  { id: 1, name: "Ada" },
3  { id: 2, name: "Linus" },
4  { id: 1, name: "Ada" },
5];
6
7const deduped = [...new Map(users.map(user => [user.id, user])).values()];
8
9console.log(deduped);

This keeps the last object seen for each id. If you want to keep the first object instead, only set the key if it is not present:

javascript
1const seen = new Map();
2
3for (const user of users) {
4  if (!seen.has(user.id)) {
5    seen.set(user.id, user);
6  }
7}
8
9const firstWins = [...seen.values()];
10console.log(firstWins);

When an id or other stable key exists, this is usually the cleanest and fastest solution.

Deduplicating By Multiple Properties

Sometimes one field is not enough, so you can build a compound key:

javascript
1const items = [
2  { type: "book", title: "Dune" },
3  { type: "book", title: "Dune" },
4  { type: "movie", title: "Dune" },
5];
6
7const keyFor = item => `${item.type}::${item.title}`;
8const uniqueItems = [...new Map(items.map(item => [keyFor(item), item])).values()];
9
10console.log(uniqueItems);

This works well as long as the chosen fields truly define equality for your application.

A Generic filter Pattern

If you prefer filter, use a Set of keys:

javascript
1const seenKeys = new Set();
2
3const result = items.filter(item => {
4  const key = `${item.type}::${item.title}`;
5  if (seenKeys.has(key)) {
6    return false;
7  }
8  seenKeys.add(key);
9  return true;
10});
11
12console.log(result);

This keeps the first matching object and reads well in pipelines.

What About JSON.stringify?

You will often see this pattern:

javascript
const unique = [...new Set(items.map(item => JSON.stringify(item)))].map(str => JSON.parse(str));

It can work for small simple objects, but it has tradeoffs:

  • Property order affects the string output.
  • Functions, undefined, and special values are not preserved reliably.
  • Nested objects can make the key generation expensive.
  • Parsing back into objects creates new objects rather than keeping originals.

Because of that, JSON.stringify is a convenient shortcut, not a universal equality strategy.

Reusable Helper Function

A practical helper is a function that accepts a key selector:

javascript
1function uniqueBy(array, keySelector) {
2  const seen = new Set();
3
4  return array.filter(item => {
5    const key = keySelector(item);
6    if (seen.has(key)) {
7      return false;
8    }
9    seen.add(key);
10    return true;
11  });
12}
13
14const uniqueUsers = uniqueBy(users, user => user.id);
15console.log(uniqueUsers);

This keeps the equality rule explicit and reusable.

Common Pitfalls

The biggest mistake is assuming object equality works like primitive equality. Two objects with identical fields are still different if they are different references.

Another pitfall is choosing the wrong deduplication key. If the key is not truly unique for the business meaning of the data, you may delete legitimate records by accident.

Developers also sometimes reach for JSON.stringify on large or complex objects without considering performance and serialization edge cases. It is fine for prototypes, but often too fragile for production logic.

Finally, be clear about whether the first duplicate should win or the last duplicate should win. Map and filter patterns can do either, but the code should make that choice obvious.

Summary

  • Objects in JavaScript are compared by reference, not by property values.
  • If a stable key such as id exists, use a Map or Set keyed by that field.
  • For multi-field equality, build an explicit compound key.
  • 'JSON.stringify can work for simple cases but has real limitations.'
  • Decide whether your deduplication should keep the first match or the last match.

Related reading
Course
Intermediate
27 lessons
15 hours
DSA Fundamentals

Master algorithmic patterns and data structures through hands-on LeetCode-style problems - from arrays and hashing to dynamic programming and advanced graphs.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Data Structures & Algorithms practice on Codemia

Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.

Practice algorithms

All Rights Reserved.