JavaScript中indexOf方法在一个数组的数组中无法找到数组。

9

我有一个包含嵌套数组的数组,看起来像这样:

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

当我尝试查找数组tw是否包含传入的数组时,我总是得到-1的结果。

例如:

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

即使数组中的第一个对象是[3,0],两者都返回-1。如何判断特定的数组是否包含在我的数组中?

哦,目前我只在IE9上测试过。


2
indexOf使用严格相等(即===或三个等号运算符)比较搜索元素和数组元素。参见:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf。我在inarray中也没有看到数组作为目标值。参见:http://api.jquery.com/jQuery.inArray/。 - mplungjan
我建议编辑jQuery标签,因为它包括$.inArray和其他小的更改,但我不确定这是否是jQuery或者你是否想要jQuery解决方案(如果是这种情况,请撤销/改进/拒绝)。 - ajax333221
6个回答

14

那是因为你在寻找不同的对象。indexOf()使用严格相等比较(例如===运算符),[3, 0] === [3, 0]返回false。

你需要手动查找。这里有一个示例,使用更通用的indexOf()函数和一个自定义的比较函数(由@ajax333221在评论中提出的改进):

// 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

请查看这个新的示例(另一个 jsFiddle 是错误的),了解为什么应该使用 if(i in arr&&comparer(arr[i], val)) - ajax333221
@ajax333221:啊,我以为你建议使用for...in。抱歉。是的,那绝对是一个改进,尽管对于这个特定问题的情况没有任何区别,我认为明确地将数组属性设置为“未定义”会引发麻烦。我会更新我的答案。 - Tim Down

2

数组是对象。[3, 0]并不等同于 [3, 0],因为它们是不同的对象。这就是为什么你的inArray函数失效的原因。


2
因为您正在比较两个不同实例的数组。如果比较对象,只有当它们是同一实例时才返回true,无论它们包含相同的数据与否都不重要。
在您的情况下,您可以采用以下方法:
var tw = [[3, 0], [11, 0], [3, 14], [11, 14]];

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

或者更传统的做法是:
if (tw.filter(function(v) { return String(v) === String([3, 10]) })[0]) {
   // ...
}

条件的调整取决于数组的内容。


2

对于无限嵌套搜索:

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;
}

注意:

  • 支持无限嵌套数组
  • 正确处理稀疏数组
  • 使用 typeof 检查

jsFiddle 示例


我花了数小时才弄清楚 NaN!==NaNtrue,以及 typeof null"object" - ajax333221

0

为什么不保持简单呢?

function indexOfCustom (parentArray, searchElement) {
    for ( var i = 0; i < parentArray.length; i++ ) {
        if ( parentArray[i][0] == searchElement[0] && parentArray[i][1] == searchElement[1] ) {
            return i;
        }
    }
    return -1;
}

0

这是因为$.inArrayindexOf都使用===进行浅比较。

由于你传递给indexOf的数组与你的二维数组中的数组在内存中不完全相同,===返回false。你需要进行深度比较才能正确地找到数组 - 从快速查看jQuery文档来看,这并不可用。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接