0

I have arr = [1,2,3] and ids = [1,2,3,4,5,6]. I want to find if any of the arr item exist in the ids. If yes the invalid is true.

Which of the below code is better? or they are the same thing?

const invalid = !arr.every((id) => ~ids.indexOf(id));

const invalid = arr.some((id) => ids.includes(id));
6
  • what is ~ in first statement? Commented Mar 15, 2022 at 6:49
  • 1
    @Nitheesh developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… Commented Mar 15, 2022 at 6:52
  • const invalid = !arr.every((id) => ~ids.indexOf(id); this is an invalid syntax. Missing ). If that is added, it will show false as output which is not the expected one. Commented Mar 15, 2022 at 6:55
  • @Nitheesh ~ids.indexOf(id) is an obscure way of doing ids.indexOf(id) >= 0. Since ~(-1) is 0 which is falsy. Whereas ~N (where N is a non-negative integer aka natural number) produces some negative integer which is truthy. Commented Mar 15, 2022 at 10:15
  • @3limin4t0r actually ~someNumber is a way of checking if someNumber != -1 and I personally find nothing obscure about it. Especially in the context of indexOf because the "negative" (ie -1 = element is not found) result of indexOf is actually a truthy, whereas one "positive" result (ie 0 = element is found at index 0) is a falsey, and the ~ converts -1 to a falsey and 0 to a truthy. But for only checking if an element is contained, I'd prefer includes Commented Mar 15, 2022 at 10:28

1 Answer 1

2

The two statements have a very different semantics.

The callbacks are the same, ie ids.includes(id) === true is equivalent to ~ids.indexOf(id) != 0. But arr.some() and !arr.every() have a different semantics:

  • some() returns true if at least one element fits the condidition
  • !every() returns true if at least one element doesn't fit the condition

So actually your first snippet is not checking, if there is at least one element in arr that is also contained in ids, but if there is at least one element in arr that is not contained in ids

So the correct version of first snippet would be

const invalid = !arr.every((id) => !(~ids.indexOf(id)));

Ie, checkig if not every element of arr is not contained in ids. From a computational standpoint, they are more or less the same:

  • indexOf and includes return on the first element element they find
  • some stops when the callback returns true for the first time
  • every stops when the callback returns false for the first time
  • there is of course a (little) overhead for ~ and !

But if you compare this to your second snippet, it seems pretty obvious, that it is far more complex to read and understand and therefore far more complex to maintain.

const 
  arr = [1,2,3],
  ids = [1,2,3,4,5,6]
  
const 
  i1 = !arr.every((id) => ~ids.indexOf(id)),
  i2 = arr.some((id) => ids.includes(id)),
  i3 = !arr.every((id) => !(~ids.indexOf(id)));
  
  
console.log(i1, i2, i3)

Sign up to request clarification or add additional context in comments.

2 Comments

so your conclusion is stop using ! and every?
In that particular usecase, yes. because arr.some(id => ids.includes(id)) also verbally expresses, what you are trying to do, ie check if "some" elements of arr are also "included" in ids ...

Your Answer

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