I’m trying to find items from one list that are not in items in a second list. Almost by dumb luck I got it to work, but only with arrow functions. For me normal functions are easier to read so I tried converting it and the result isn’t what I expect.
data:
const arr1 = [ { "key": 1, "val": "one" }, { "key": 2, "val": "two" }, { "key": 3, "val": "three" } ] const arr2 = [ { "key": 3, "val": "three" }, { "key": 4, "val": "four" }, { "key": 1, "val": "one" } ]
version 1
arr1.filter((element) => arr2.findIndex((innerElement) => element.key === innerElement.key) === -1); // produces object with key 2
version 2
arr1.filter(function(element) { return arr2.findIndex(function(innerElement) { element.key === innerElement.key === -1 }) }) // produces all three objects in arr1
To make the correct one more terse I removed extra parentheses and it still works:
arr1.filter(element => arr2.findIndex(innerElement => element.key === innerElement.key) === -1);
I’m missing a key aspect here. I get that each item in arr1 is passed to a function and that inner function in turn passes its result to another function and the expression has access to both sets of arguments and gets executed. But I think I have the wrong mental model about the order or something.
Can someone explain what is happening in each step and how to think about it? And how do I make it into a normal function?
I’ll be dealing with a lot of nested structures and I feel this is a weak area that I’d like to get better in.
Thank you
Advertisement
Answer
You need to return the value of the comparison. And the === -1
test must be with the result of findIndex()
, not inside its callback.
arr1.filter(function(element) { return arr2.findIndex(function(innerElement) { return element.key === innerElement.key; }) === -1; });
This can be simplified with the some()
method.
arr1.filter(function(element) { return !arr2.some(function(innerElement) { return element.key === innerElement.key }) })