Skip to content
Advertisement

Remove array objects contained in another array by value

I have to remove all the objects from array that contain the same id present in another array.

This code works

myArray = [{id: 1, value: 'a'}, {id: 2, value: 'b'}, {id: 3, value: 'c'}];
itemsToRemove = [{id: 2, value: 'x'}, {id: 3, value: 'y'}];
for (const item of itemsToRemove) {
    myArray.splice(myArray.findIndex(a => a.id === item.id), 1);
}

but I’m looking for a more elegant way to do it. I’ve tried also

const newArray = myArray.filter(a => itemsToRemove.findIndex(i => i.id === a.id));

but doesn’t works. (it creates a new array, but at least one item with the same id remains in the new array).

Is there a clean and concise way to do it?

Answer

You’re close, but as James said in the comments, findIndex is the wrong choice because it returns -1 when the item is not found. filter requires its predicate to return a boolean and -1 is not a boolean, so it’s coerced to one. Unfortunately, -1 is truthy which doesn’t match your intention in the predicate.

You can add a comparison to check that findIndex returned a value less than zero, or you can use find or some:

const myArray = [{id: 1, value: 'a'}, {id: 2, value: 'b'}, {id: 3, value: 'c'}];
const itemsToRemove = [{id: 2, value: 'x'}, {id: 3, value: 'y'}];

const newArray1 = myArray.filter(a => itemsToRemove.findIndex(i => i.id === a.id) < 0);
console.log(newArray1);

const newArray2 = myArray.filter(a => !itemsToRemove.find(i => i.id === a.id));
console.log(newArray2);

const newArray3 = myArray.filter(a => !itemsToRemove.some(i => i.id === a.id));
console.log(newArray3);

It’s worth noting that find isn’t supported in IE, nor is findIndex. some is supported by all browsers, so it’s the most compatible.

some is also the most performant:

JSBench.me screenshot showing the results in the table below

Test Result Operations/second
findIndex 10.63% slower 26632285
find 12.39% slower 26107649
some fastest 29799972
Advertisement