'Check if an array includes an array in javascript

The javascript includes function can be used to find if an element is present in an array. Take the following example:

var arr = ['hello', 2, 4, [1, 2]];

console.log( arr.includes('hello') );
console.log( arr.includes(2) );

console.log( arr.includes(3) );

console.log( arr.includes([1, 2]) );

Passing 'hello' or 2 to the function returns true, as both are present in the array arr.

Passing 3 to the function returns false because it is not present in the array.

However, why does arr.includes([1, 2]) return false as well, even though this is equal to the last element in the array? And if this method does not work, how else can I find whether my array includes the item [1, 2]?



Solution 1:[1]

The Array#includes checks by shallow comparison, so in your case the string and numbers are primitives there is only ever a single instance of them so you get true from Array#includes.

But when you check for array, you are passing a new array instance which is not the same instance in the array you are checking so shallow comparison fails.

To check for an array is included in another array first check if it is an array then do a deep comparison between the arrays.

  • Note that below snippet only works for an array of primitives:

var arr = ['hello', 2, 4, [1, 2]];
const includesArray = (data, arr) => {
  return data.some(e => Array.isArray(e) && e.every((o, i) => Object.is(arr[i], o)));
}

console.log(includesArray(arr, [1, 2]));

But if you keep the reference to the array [1, 2] and search with the reference the Array#includes works as in this case the shallow comparison works perfectly (obeying same value zero algorithm):

const child =  [1, 2];
const arr = ['hello', 2, 4, child];

console.log(arr.includes(child));

Solution 2:[2]

.includes() method uses sameValueZero equality algorithm to determine whether an element is present in an array or not.

When the two values being compared are not numbers, sameValueZero algorithm uses SameValueNonNumber algorithm. This algorithm consists of 8 steps and the last step is relevant to your code , i.e. when comparison is made between two objects. This step is:

  1. Return true if x and y are the same Object value. Otherwise, return false.

So in case of objects, SameValueZero algorithm returns true only if the two objects are the same.

In your code, since the array [1, 2] inside arr array is identically different to [1, 2] that you passed to .includes() method, .includes() method can't find the array inside arr and as a result returns false.

Solution 3:[3]

If you don't mind using lodash, this algorithm is accurate - unlike the accepted answer.

import _ from 'lodash';

export const includesArray = (haystack, needle) => {
    for (let arr of haystack)
        if (_.isEqual(arr, needle)) {
            return true
    }
    return false
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2
Solution 3 abulka