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?
Advertisement
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:
Test | Result | Operations/second |
---|---|---|
findIndex | 10.63% slower | 26632285 |
find | 12.39% slower | 26107649 |
some | fastest | 29799972 |