Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript indexOf for an array of arrays not finding array

I have an array with nested arrays that looks like this:

var tw = [[3, 0], [11, 0], [3, 14], [11, 14]];

When I try and find if the array tw contains a passed in array, I always get a result of -1.

For example:

var test = $.inArray([3, 0], tw);
var test2 = tw.indexOf([3, 0]);

both return -1, even though the first object in the array is [3,0] How do I find out if a specific array of arrays is contained in my array?

Oh, and I've only tested it on IE9 so far.

like image 363
joe_coolish Avatar asked Apr 21 '12 15:04

joe_coolish


People also ask

What does array indexOf return if it doesn't find the element?

indexOf() The indexOf() method returns the first index at which a given element can be found in the array, or -1 if it is not present.

Can you use indexOf for an array?

Introduction to the JavaScript array indexOf() method To find the position of an element in an array, you use the indexOf() method. This method returns the index of the first occurrence the element that you want to find, or -1 if the element is not found.

Does indexOf work on 2d arrays?

You cannot use indexOf to do complicated arrays (unless you serialize it making everything each coordinate into strings), you will need to use a for loop (or while) to search for that coordinate in that array assuming you know the format of the array (in this case it is 2d).

Can you use indexOf on an array of objects JavaScript?

To find the index of an object in an array, by a specific property: Use the map() method to iterate over the array, returning only the value of the relevant property. Call the indexOf() method on the returned from map array. The indexOf method returns the index of the first occurrence of a value in an array.


4 Answers

That's because you're searching for a different object. indexOf() uses strict equality comparisons (like the === operator) and [3, 0] === [3, 0] returns false.

You'll need to search manually. Here's an example using a more generic indexOf() function that uses a custom comparer function (with an improvement suggested by @ajax333221 in the comments):

// Shallow array comparer
function arraysIdentical(arr1, arr2) {
    var i = arr1.length;
    if (i !== arr2.length) {
        return false;
    }
    while (i--) {
        if (arr1[i] !== arr2[i]) {
            return false;
        }
    }
    return true;
}

function indexOf(arr, val, comparer) {
    for (var i = 0, len = arr.length; i < len; ++i) {
        if ( i in arr && comparer(arr[i], val) ) {
            return i;
        }
    }
    return -1;
}

var tw = [[3, 0], [11, 0], [3, 14], [11, 14]];
alert( indexOf(tw, [3, 0], arraysIdentical) ); // Alerts 0
like image 99
Tim Down Avatar answered Oct 25 '22 06:10

Tim Down


Arrays are objects. [3, 0] does not equal [3, 0] as they are different objects. That is why your inArray fails.

like image 32
Gwyn Howell Avatar answered Oct 25 '22 07:10

Gwyn Howell


Because you're comparing two difference instance of array. Comparing objects returns true only if they're the same instance, it doesn't matter if they contain the same data.

In your case, you could use this approach:

var tw = [[3, 0], [11, 0], [3, 14], [11, 14]];

if (~tw.join(";").split(";").indexOf(String([3, 0]))) {
    // ...
}

Or something more ortodox like:

if (tw.filter(function(v) { return String(v) === String([3, 10]) })[0]) {
   // ...
}

Where the condition can be adjusted depends by the content of the arrays.

like image 43
ZER0 Avatar answered Oct 25 '22 07:10

ZER0


For infinite nested search:

function indexOfArr(arr1, fnd1) {
    var i, len1;

    //compare every element on the array
    for (i = 0, len1 = arr1.length; i < len1; i++) {

        //index missing, leave to prevent false-positives with 'undefined'
        if (!(i in arr1)) {
            continue;
        }

        //if they are exactly equal, return the index
        if (elementComparer(arr1[i], fnd1)) {
            return i;
        }
    }

    //no match found, return false
    return -1;
}

function elementComparer(fnd1, fnd2) {
    var i, len1, len2, type1, type2, iin1, iin2;

    //store the types of fnd1 and fnd2
    type1 = typeof fnd1;
    type2 = typeof fnd2;

    //unwanted results with '(NaN!==NaN)===true' so we exclude them
    if (!((type1 == "number" && type2 == "number") && (fnd1 + "" == "NaN" && fnd2 + "" == "NaN"))) {

        //unwanted results with '(typeof null==="object")===true' so we exclude them
        if (type1 == "object" && fnd1 + "" != "null") {
            len1 = fnd1.length;

            //unwanted results with '(typeof null==="object")===true' so we exclude them
            if (type2 == "object" && fnd2 + "" != "null") {
                len2 = fnd2.length;

                //if they aren't the same length, return false
                if (len1 !== len2) {
                    return false;
                }

                //compare every element on the array
                for (i = 0; i < len1; i++) {

                    iin1 = i in fnd1;
                    iin2 = i in fnd2;

                    //if either index is missing...
                    if (!(iin1 && iin2)) {

                        //they both are missing, leave to prevent false-positives with 'undefined'
                        if (iin1 == iin2) {
                            continue;
                        }

                        //NOT the same, return false
                        return false;
                    }

                    //if they are NOT the same, return false
                    if (!elementComparer(fnd1[i], fnd2[i])) {
                        return false;
                    }
                }
            } else {
                //NOT the same, return false
                return false;
            }
        } else {

            //if they are NOT the same, return false
            if (fnd1 !== fnd2) {
                return false;
            }
        }
    }

    //if it successfully avoided all 'return false', then they are equal
    return true;
}

Notes:

  • supports infinite nested arrays
  • handles sparse arrays correctly
  • uses typeof checks

jsFiddle demo

like image 25
ajax333221 Avatar answered Oct 25 '22 06:10

ajax333221