Skip to main content

How to remove duplicates from an object array?

Reviewing a recent code exercise at work, we came across a situation where a candidate wanted to ensure that there were no duplicates in an array of objects.

The solution, which seemed to have been cobbled together from suggestions in this Stack Overflow thread, included Array.from(), new Set, Array.map(), and Array.find().

It worked, but it definitely fulfilled the definition of “frankencode”.

Let’s look at a simpler solution to this common problem with a simple O(n) complexity.

Setup

The data here could be pretty complicated, so I’m going to reduce it to the simplest form. We have an array of possibly duplicate objects, and we’ll know that they’re duplicated based on the name key:

const listWithDups = [
  { name: "one" },
  { name: "two" },
  { name: "one" }, // <-- Duplicate
  { name: "three" },
];

We want to be able to loop through this data as few times as possible in order to remove that duplicate entry.

Steps

There are a few things that we are going to need in order to solve this problem. First, we’re going to need a new array to which we’ll add unique items. Second, we’re going to need a way to keep track of the items that we have already seen. And third, we’re going to need a way to iterate through the data.

Let’s look at those one at a time.

New array

For this process, we want this to create a new unique array without modifying the original. This is a good practice, because it gives you the ability to compare your data down the road.

const uniqueList = [];

When we are iterating through our original array and come across a unique object, we’ll add it to uniqueList with Array.push().

Unique key tracker

In order to know if an object is unique, we need to know all of the keys that we have seen before.

There are a few different data types that we could use, but the best option here is an object; they’re perfect for looking up information based on a known key.

This object only exists to track those keys. It will not be returned and no other process depends on its information. That makes it a temporary variable, and we should name it as such:

const temp = {};

For every object in our list, we’ll check to see if their name key exists on our temp object. If it does not, then we’ll add it to the object and then add the object to the unique list. If it does not, then we know that it is a duplicate and can move on.

Iterate

Since we are going to be iterating through data, the easiest1 way to do that is with a for loop. We’re going to use a for...of here because we don’t care about the index number:

for (let item of listWithDups) {
  // TODO: Check if item is unique.
  // If so, add it to the list and remember it's name.
  // If not, pass over; it's a duplicate.
}

Now we can go about implementing the steps above.

Since we’re using our temp object to track all of the items that we have already encountered, we can check to see if each item’s name exists as a key on temp.

Note: We haven’t written the logic to add items to temp yet, but we know that this is how we want the application to work.

for (let item of listWithDups) {
  // If we haven't seen this name before...
  if (!temp[item.name]) {
  }
}

Within this if block, we’ll do our “unique name” logic. We want to add the item to our unique list and remember the name for next time.

for (let item of listWithDups) {
  // If we haven't seen this name before...
  if (!temp[item.name]) {
    uniqueItems.push(item); // Add to unique list
    temp[item.name] = true; // Remember the name
  }
}

Once that loop has run, we will have built our uniqueItems array without duplicating any values. We have successfully de-duped our array with only a single iteration!

Sample

Here is a Repl of the solution. Feel free to fork it, make improvements, and share your code with me.

Happy coding!

Footnotes

  1. YMMV