0

In javascript there is function Array.prototype.includes() which is useful when we want to find some value in array. It's working fine when we search string, object or number value. However it seems not working when we trying to find an array in array

let internalArray = ["a","b"]
let arrayOfArrays = [internalArray]
let result = arrayOfArrays.includes(["a","b"]);

But this is working :D

let internalArray = ["a","b"]
let arrayOfArrays = [internalArray]
let result = arrayOfArrays.includes(internalArray);

So it seems that when we use includes function javascript is comparing the array references but not the values i am right?

The next question is - how to find an array in array in another way - which compares the internal values?

Patrick Roberts
  • 49,224
  • 10
  • 102
  • 153
Nicramus
  • 606
  • 1
  • 6
  • 19
  • With `includes(internalArray);` you ask if the `internalArray` exists, and it might exist. With `includes(["a","b"]);` you ask if the literal array you just created `["a","b"]` exists in the array, and that can never be true, because you just created it, and it only exists while you are looking for it. – some Sep 24 '19 at 22:01

2 Answers2

1

You can use .some() and pass a partially applied predicate that compares the two parameters for array equality by comparing lengths and calling .every() to check each element for equality:

let equal = a => b =>
  a.length === b.length &&
  a.every((v, i) => v === b[i])

let internalArray = ["a","b"]
let arrayOfArrays = [internalArray]
let result = arrayOfArrays.some(equal(["a","b"]))

console.log(result)
Patrick Roberts
  • 49,224
  • 10
  • 102
  • 153
-1

suppose main array is a: [[1,2],4,5,6] and the array to search for is b: [1,2]

then you could do:

a.some(function(d){
    return d instanceof Array && this.every((el)=>~d.indexOf(el))
},b)

I passed b as "thisArg" and check only the elements that are arrays. If you have more strict requirements you can try below one:

a.some(function(d){
    if(!(d instanceof Array)){return}
    let copy = this.slice(),_d = d.slice(),_i; 
    this.forEach((el)=>~(_i = _d.indexOf(el)) && _d.splice(_i,1) && copy.splice(copy.indexOf(el),1));
    return !copy.length;
},b)
ibrahim tanyalcin
  • 5,643
  • 3
  • 16
  • 22
  • This assumes that any array in `a` is the same length as `b`, and it does not ensure that the elements are in the same order. If a is `[[1, 2, 3], 4, 5]` and b is `[1, 1]`, this returns `true`. – Patrick Roberts Sep 24 '19 at 22:21
  • hmm, I skipped that, I think I can modify a bit.The length doesn't have to be equal though, but the elements should be contained I think, then its O(n) ish. – ibrahim tanyalcin Sep 24 '19 at 23:04
  • The length _does_ have to be equal. What makes you think otherwise? – Patrick Roberts Sep 24 '19 at 23:10
  • 'Contained' is sufficient, otherwise last line can be !copy.length && !_d.length. I'd leave it out. – ibrahim tanyalcin Sep 24 '19 at 23:11
  • I see what you mean now. Took a while to follow what that code is trying to do, I imagine that solution would be hard to maintain. Also both your approaches are O(n^2), not O(n). – Patrick Roberts Sep 24 '19 at 23:24
  • If the solution would not be "contained by" and indexes, length and order should be same I was asking why one does not use toString or JSON.stringify to directly compare, so I assumed 'contained'.O(n^2) because of the indexOf's I had to use, walking the arrays once with for loop would look longer, but less than On^2. He accepted your answer, so I won't dig into that – ibrahim tanyalcin Sep 25 '19 at 06:02