0

I have an array of objects that looks something like (rough example):

[{id:1, stuff:moreStuff}, {id:6, manyStuff,Stuffing}, {id:4, yayStuff, stuff}, {id:6, manyStuff, Stuffing}] 

The problem is that in the array, there are several duplicate objects. The current solution I've thought of so far is something along the lines of this:

const DuplicateCheck = []
const FinalResult = []

for (let i = 0; i < ArrayOfObjects.length; i++) {
    let isPresent = false;
    for (let j = 0; j < duplicateCheck.length; j++) {
        if (ArrayOfObjects[i].id == duplicateCheck[j]) {
            isPresent = true;
        }
    }
    if (isPresent = false) {
        DuplicateCheck.push(ArrayOfObjects[i].id
        FinalResult.push(ArrayOfObjects[i]
    }
}

Now after learning big O, it seems like this is a very inefficient way to go about doing this problem. So my question is, is there a better, more efficient way to solve this problem?

10
  • One approach: Sort into array 2, copy back. If the array is sorted, duplicates appear one after the other so you only need to look at the previous value. O ( n log n ) sort + O ( n ) copy. There might be better approaches if you google, like adding to hash table and copying back from that? Commented Jul 27, 2020 at 20:32
  • If one were to map the objects to JSON strings, create a new Set from that, create a new Array from the set, then map the now unique elements back to objects, what would be the O of that? Commented Jul 27, 2020 at 20:44
  • 1
    Does this answer your question? Remove duplicates from an array of objects in JavaScript Commented Jul 27, 2020 at 20:44
  • I don't get points for closing questions as a dupe. You'd know that if you read the privileges page instead of going with your prejudices. Also, you're not the OP @GirkovArpa, so why are you even responding? Commented Jul 27, 2020 at 20:49
  • @GirkovArpa: Removing duplicate questions is a community service, earning no reputation points or other rewards. Commented Jul 27, 2020 at 20:50

4 Answers 4

1

Yes, use a Set for your DuplicateCheck which gives you O(1) access by id:

const duplicateCheck = new Set
const finalResult = []

for (const object of arrayOfObjects) {
    if (!duplicateCheck.has(object.id)) {
        duplicateCheck.add(object.id)
        finalResult.push(object)
    }
}
Sign up to request clarification or add additional context in comments.

2 Comments

Shouldn't new Set be new Set()? Or are the parentheses optional these days?
@3limin4t0r Parenthesis for constructor calls have always been optional :-)
0

You could iterate over the array and store the id in and object (hash table) and then check if exist. Something like:

const DuplicateCheck = {}
const FinalResult = []

for (let i = 0; i < ArrayOfObjects.length; i++) {
    let currentId = ArrayOfObjects[i].id

    if (!DuplicateCheck[currentId]) {
        DuplicateCheck[currentId] = 1
        FinalResult.push(ArrayOfObjects[i])
    }
}

And you will receive all unique objects in the FinalResult

Comments

0

You could keep usedIds as object properties and add to the filtered array only if the object has no such property or just add your items in Set if that's a possibility for you. Set as a data structure can only store non-duplicates.

Without Set:

const filteredArray = [];
const usedIds = {};

for (const item of array) {
  if (!usedIds[item.id]) {
    usedIds[item.id] = true;
    filteredArray.push(item);
  }
}

With Set:

const filteredArray = [];
const usedIds = new Set();

for (const item of array) {
  if (!usedIds.has(item.id)) {
    usedIds.add(item.id);
    filteredArray.push(item);
  }
}

Runnable example:

const array = [
  {
    id: 1,
    stuff: 'stuff',
    moreStuff: 'moreStuff'
  },
  {
    id: 6,
    manyStuff: 'manyStuff',
    stuffing: 'stuffing'
  },
  {
    id: 4,
    yayStuff: 'yayStuff',
    stuff: 'stuff'
  },
  {
    id: 6,
    manyStuff: 'manyStuff',
    stuffing: 'stuffing'
  }
];

const filteredArray = [];
const usedIds = {};

for (const item of array) {
  if (!usedIds[item.id]) {
    usedIds[item.id] = true;
    filteredArray.push(item);
  }
}

console.log(filteredArray);

Comments

0

You can also use a Map to filter out duplicates. Contrary to the Set approach by Bergi this solution leaves the last version of the duplicate, since it overrides the key/value-pair with the same key.

const objectsById = new Map(arrayOfObjects.map(object => [object.id, object]));
const finalResult = Array.from(objectsById.values());

The code above does need to iterate the collection 2 times. Once using map to create key/value-pairs and once when the created array is converted to a Map.

When the resulting objectsById is created we'll have to iterate over the values to convert them back to array.

In total this means between 2 and 3 iterations over the full collection, which more often then not still a lot faster then solutions using find. Since that iterates over the array every time it is called.

You can reduce the amount of iterations by 1 if you omit the map call and manually insert the elements in objectsById:

const objectsById = new Map();
for (const object of arrayOfObjects) {
  objectsById.set(object.id, object);
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.