13

I needed 2d arrays, so I made a nested array since JavaScript doesn't allow them.

They look like this:

var myArray = [
  [1, 0],
  [1, 1],
  [1, 3],
  [2, 4]
]

How can I check if this array includes a specific element (i.e. one of these [0,1] arrays) in vanilla JS?

Here is what I tried, with no success (everything returns false) (EDIT: I included the answers in the snippet):

var myArray = [
  [1, 0],
  [1, 1],
  [1, 3],
  [2, 4]
]

var itemTrue = [2, 4];
var itemFalse = [4, 4];

function contains(a, obj) {
  var i = a.length;
  while (i--) {
    if (a[i] === obj) {
      return true;
    }
  }
  return false;
}

// EDIT: first answer's solution

function isArrayInArray(x, check) {
  for (var i = 0, len = x.length; i < len; i++) {
    if (x[i][0] === check[0] && x[i][1] === check[1]) {
      return true;
    }
  }
  return false;
}

// EDIT: accepted answer's solution


function isArrayInArray2(x, check) {
  var result = x.find(function(ele) {
    return (JSON.stringify(ele) === JSON.stringify(check));
  }) 
  return result !=null
}

console.log("true :" + myArray.includes(itemTrue));
console.log("false :" + myArray.includes(itemFalse));

console.log("true :" + (myArray.indexOf(itemTrue) != -1));
console.log("false :" + (myArray.indexOf(itemFalse) != -1));

console.log("true :" + contains(myArray, itemTrue));
console.log("false :" + contains(myArray, itemFalse));

// EDIT: first answer's solution
console.log("true :" + isArrayInArray(myArray, itemTrue));
console.log("false :" + isArrayInArray(myArray, itemFalse));


// EDIT: accepted answer's solution
console.log("true :" + isArrayInArray2(myArray, itemTrue));
console.log("false :" + isArrayInArray2(myArray, itemFalse));

It could look like duplicate but I couldn't find a similar question. If it is, feel free to tag it as such.

Audwin Oyong
  • 2,247
  • 3
  • 15
  • 32
Billybobbonnet
  • 3,156
  • 4
  • 23
  • 49
  • 1
    Possible duplicate of [How do I check if an array includes an object in JavaScript?](http://stackoverflow.com/questions/237104/how-do-i-check-if-an-array-includes-an-object-in-javascript) – iwaduarte Jan 15 '17 at 12:54
  • I read that question and it didn't solve my problem. See the updated snippet with that question's answer 2 solution added. – Billybobbonnet Jan 15 '17 at 12:59
  • Internally, the function would check `if (paramArray[i] == searchElement)`, which fails, because you can't compare two arrays using `==`, so you can't use `includes` to do this. – pushkin Jan 15 '17 at 13:02
  • Duplicate http://stackoverflow.com/questions/6315180/javascript-search-array-of-arrays – Asif Saeed Jan 15 '17 at 13:03
  • Again, considering that this is a specific case (pseudo 2d arrays), this isn't a duplicate of http://stackoverflow.com/questions/6315180/javascript-search-array-of-arrays which didn't solve directly my question. Pls remove the flags – Billybobbonnet Jan 15 '17 at 13:18

6 Answers6

13

Short and easy, stringify the array and compare as strings

function isArrayInArray(arr, item){
  var item_as_string = JSON.stringify(item);

  var contains = arr.some(function(ele){
    return JSON.stringify(ele) === item_as_string;
  });
  return contains;
}

var myArray = [
  [1, 0],
  [1, 1],
  [1, 3],
  [2, 4]
]
var item = [1, 0]

console.log(isArrayInArray(myArray, item));  // Print true if found

check some documentation here

mohamed-ibrahim
  • 10,837
  • 4
  • 39
  • 51
  • 1
    Thank you. I updated my snippet with your code, in the form a a function. – Billybobbonnet Jan 15 '17 at 13:15
  • Though this is simple, I feel like it is more correct to loop through the arrays and compare each element. It's also faster: https://jsperf.com/comparing-arrays2 – pushkin Jan 15 '17 at 13:40
  • i updated to stringify check item only once at beginning, and also here all items are nested array which will do a recursion for each item, all of that should be considered – mohamed-ibrahim Jan 15 '17 at 13:46
  • This works fine as long as all items are serializable, but not for the general case. Also, you'd be better of with `.some` instead of `.find` + `=null`. – georg Jan 15 '17 at 14:17
  • As mentioned in the [comments here](https://stackoverflow.com/a/68747829/6908282), this doesn't work when `item = ['1', 0]` – Gangula Nov 17 '22 at 08:09
5

A nested array is essentially a 2D array, var x = [[1,2],[3,4]] would be a 2D array since I reference it with 2 index's, eg x[0][1] would be 2.

Onto your question you could use a plain loop to tell if they're included since this isn't supported for complex arrays:

var x = [[1,2],[3,4]];
var check = [1,2];
function isArrayInArray(source, search) {
    for (var i = 0, len = source.length; i < len; i++) {
        if (source[i][0] === search[0] && source[i][1] === search[1]) {
            return true;
        }
    }
    return false;
}
console.log(isArrayInArray(x, check)); // prints true

Update that accounts for any length array

function isArrayInArray(source, search) {
    var searchLen = search.length;
    for (var i = 0, len = source.length; i < len; i++) {
        // skip not same length
        if (source[i].length != searchLen) continue;
        // compare each element
        for (var j = 0; j < searchLen; j++) {
            // if a pair doesn't match skip forwards
            if (source[i][j] !== search[j]) {
                break;
            }
            return true;
        }
    }
    return false;
}
console.log(isArrayInArray([[1,2,3],[3,4,5]], [1,2,3])); // true
dayvidwhy
  • 76
  • 1
  • 5
  • Thank you. That's working fine. I chose the other answer because it looks simpler. I updated my snippet with your answer. – Billybobbonnet Jan 15 '17 at 13:15
  • The crucial part is compare lengths of both arrays before looping, consider `check = [1,2,99]` – georg Jan 15 '17 at 14:21
  • Yes definitely we could take this further and let it work for any length array, I've updated the post with another solution that takes this into account. – dayvidwhy Jan 15 '17 at 14:33
4

Here is an ES6 solution:

myArray.some(
    r => r.length == itemTrue.length &&
         r.every((value, index) => itemTrue[index] == value)
);

Check the JSFiddle.

Take a look at arrow functions and the methods some and every of the Array object.

Jefferson Lima
  • 5,186
  • 2
  • 28
  • 28
3

You can't do like that .instance you have to do some thing by your own .. first you have to do a foreach from your array that you want to search and run 'compareArray' function for each item of your array .

function compareArray( arrA, arrB ){

    //check if lengths are different
    if(arrA.length !== arrB.length) return false;


    for(var i=0;i<arrA.length;i++){
         if(arrA[i]!==arrB[i]) return false;
    }

    return true;

}
1

The code provided by D. Young's comment that checks for any length array is faulty. It only checks if the first element is the same.

A corrected version of D. Young's comment:

function isArrayInArray(source, search) {
    var searchLen = search.length;
    for (var i = 0, len = source.length; i < len; i++) {
        // skip not same length
        if (source[i].length != searchLen) continue;
        // compare each element
        for (var j = 0; j < searchLen; j++) {
            // if a pair doesn't match skip forwards
            if (source[i][j] !== search[j]) {
                break;
            } else if (j == searchLen - 1) {return true}
        }
    }
    return false; 
}
Dion Chan
  • 31
  • 5
0

For those who are interested in finding an array inside another and get back an index number, here's a modified version of mohamed-ibrahim's answer:

function findArrayInArray(innerArray, outerArray) {
    const innerArrayString = JSON.stringify(innerArray);
    let index = 0;
    const inArray = outerArray.some(function (element) {
        index ++;
        return JSON.stringify(element) === innerArrayString;
    });
    if (inArray) {
        return index - 1;
    } else {
        return -1;
    }
}
findArrayInArray([1, 2, 3], [[3, .3], [1, 2, 3], [2]]); // 1
findArrayInArray([1, 2, 3], [[[1], 2, 3], [2]]) // -1

This function returns the index of the array you are searching inside the outer array and -1 if not found.

Checkout this CodePen.

AlienKevin
  • 2,691
  • 2
  • 17
  • 19