我想比较两个数组。。。理想地、有效地。没有什么稀奇古怪的,如果它们是相同的,那就是真的,如果不是,那就是假的。毫不奇怪,比较运算符似乎不起作用。

var a1 = [1,2,3];
var a2 = [1,2,3];
console.log(a1==a2);    // Returns false
console.log(JSON.stringify(a1)==JSON.stringify(a2));    // Returns true

JSON对每个数组进行编码,但是否有一种更快或“更好”的方法来简单地比较数组而不必遍历每个值?


当前回答

我们可以用功能性的方式(https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/every)

function compareArrays(array1, array2) {
    if (array1.length === array2.length)
        return array1.every((a, index) => a === array2[index])
    else
        return false
}

// test
var a1 = [1,2,3];
var a2 = [1,2,3];

var a3 = ['a', 'r', 'r', 'a', 'y', '1']
var a4 = ['a', 'r', 'r', 'a', 'y', '2']

console.log(compareArrays(a1,a2)) // true
console.log(compareArrays(a1,a3)) // false
console.log(compareArrays(a3,a4)) // false

其他回答

根据TomášZato的回答,我同意仅迭代数组是最快的。此外(就像其他人已经说过的那样),函数应该被称为equals/equal,而不是compare。考虑到这一点,我修改了该函数,以处理比较数组的相似性(即它们具有相同的元素,但没有顺序),以供个人使用,并认为我将把它放在这里让大家看到。

Array.prototype.equals = function (array, strict) {
    if (!array)
        return false;

    if (arguments.length == 1)
        strict = true;

    if (this.length != array.length)
        return false;

    for (var i = 0; i < this.length; i++) {
        if (this[i] instanceof Array && array[i] instanceof Array) {
            if (!this[i].equals(array[i], strict))
                return false;
        }
        else if (strict && this[i] != array[i]) {
            return false;
        }
        else if (!strict) {
            return this.sort().equals(array.sort(), true);
        }
    }
    return true;
}

此函数接受默认为true的strict附加参数。这个严格的参数定义数组是否需要在内容和这些内容的顺序上完全相等,或者仅仅包含相同的内容。

例子:

var arr1 = [1, 2, 3, 4];
var arr2 = [2, 1, 4, 3];  // Loosely equal to 1
var arr3 = [2, 2, 3, 4];  // Not equal to 1
var arr4 = [1, 2, 3, 4];  // Strictly equal to 1

arr1.equals(arr2);         // false
arr1.equals(arr2, false);  // true
arr1.equals(arr3);         // false
arr1.equals(arr3, false);  // false
arr1.equals(arr4);         // true
arr1.equals(arr4, false);  // true

我还编写了一个函数的快速jsfiddle,以及这个示例:http://jsfiddle.net/Roundaround/DLkxX/

本着原问题的精神:

我想比较两个数组。。。理想地、有效地。没有什么想象,如果它们是相同的,则为真,如果不是,则为假。

我一直在对这里提出的一些更简单的建议进行性能测试,结果如下(从快到慢):

而Tim Down(67%)

var i = a1.length;
while (i--) {
    if (a1[i] !== a2[i]) return false;
}
return true

每(69%)用户2782196

a1.every((v,i)=> v === a2[i]);

DEI减少(74%)

a1.reduce((a, b) => a && a2.includes(b), true);

Gaizka Allende&vivek的join&toString(78%)

a1.join('') === a2.join('');

a1.toString() === a2.toString();

Victor Palomo创作的半到字符串(90%)

a1 == a2.toString();

radtek的stringify(100%)

JSON.stringify(a1) === JSON.stringify(a2);

注意,下面的示例假设数组是排序的,一维数组。对于一个常见的基准测试,长度比较已被删除(将a1.length==a2.length添加到任何建议中,您将获得约10%的性能提升)。选择最适合您的解决方案,了解每种解决方案的速度和局限性。

代码高尔夫

有很多答案表明如何有效地比较数组。

以下是比较两个int或(字符串)数组的最短方法,以代码字节为单位。

常量a=[1,2,3]常量b=[1,2,3]console.log(“1.”,a.join()==b.join(())console.log(“2.”,a.join()==[].join())console.log(“3.”,1+a==1+b)console.log(“4.”,1+[]==1+b)//甚至更短console.log(“4.b)”,a==“”+b)//误报(见缺陷)console.log(“5.”,1+[“3”]==1+[3])//类型差异console.log(“6.”,1+[“1,2”]==1+[“1”,“2”])

解释

这是因为当使用+运算符时,类型会自动转换为允许串联。在这种情况下,1和[1,2,3]都被转换为字符串。

在内部,JavaScript使用[1,2,3].join()将数组转换为字符串,然后将它们相加,得到11,2,3。在两个数组上执行此操作时,可以简单地使用==或==来比较两个字符串。

缺陷

使用此技术,比较不关心要比较的数组中的元素是否属于不同类型。由于字符串转换,[1,2]将等于[“1”,“2”]。

编辑:正如评论中指出的,比较字符串数组可能会产生误报,例如[“1,2”]等于[“1”,“2”]。如果您确信这些情况从未发生过(例如,在许多代码高尔夫挑战中),这一点就不重要了。

免责声明

虽然这对于代码高尔夫很有用,但可能不应该在生产代码中使用。指出的两个缺陷也无助于此。

选择是否比较订单:

function arraysEqual(a1, a2, compareOrder) {
    if (a1.length !== a2.length) {
        return false;
    }

    return a1.every(function(value, index) {
        if (compareOrder) {
            return value === a2[index];
        } else {
            return a2.indexOf(value) > -1;
        }
    });
}

我会这样做:

[2,3,4,5] == [2,3,4,5].toString()

当您使用“==”运算符时,javascript检查值(左侧和右侧)是否是相同的类型,如果是不同的,javascript尝试将两边转换为相同的类型。

Array == String

Array具有toString方法,因此javascript使用它将它们转换为相同的类型,工作方式如下:

[2,3,4,5].toString() == [2,3,4,5].toString()