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

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


当前回答

不清楚你所说的“相同”是什么意思。例如,下面的数组a和b是否相同(请注意嵌套数组)?

var a = ["foo", ["bar"]], b = ["foo", ["bar"]];

这里有一个优化的数组比较函数,它使用严格的相等性依次比较每个数组的对应元素,并且不递归比较本身为数组的数组元素,这意味着对于上面的示例,arraysIncore(a,b)将返回false。它适用于一般情况,而基于JSON和join()的解决方案不会:

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

其他回答

虽然这只适用于标量数组(请参见下面的注释),但代码很短:

array1.length === array2.length && array1.every(function(value, index) { return value === array2[index]})

与上文相同,但在ECMAScript 6/CoffeeScript/TypeScript中使用箭头函数:

array1.length === array2.length && array1.every((value, index) => value === array2[index])

(注意:这里的“scalar”表示可以使用==直接比较的值。因此:数字、字符串、引用对象、引用函数。有关比较运算符的更多信息,请参阅MDN引用)。

更新

根据我在评论中看到的内容,对数组进行排序和比较可能会得到准确的结果:

const array2Sorted = array2.slice().sort();
array1.length === array2.length && array1.slice().sort().every(function(value, index) {
    return value === array2Sorted[index];
});

Eg:

array1 = [2,3,1,4];
array2 = [1,2,3,4];

然后上述代码将返回true

此外,我还根据需要将Thomas的解决方案转换为无需排序的比较。

Array.prototype.equalsFreeOrder = function (array) {
    var isThisElemExist;
    if (!array)
        return false;

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

    for (var i = 0; i < this.length; i++) {
        isThisElemExist = false;
        for (var k = 0; k < this.length; k++) {
            if (this[i] instanceof Array && array[k] instanceof Array) {
                if (this[i].equalsFreeOrder(array[k]))
                    isThisElemExist = true;
            }
            else if (this[i] == array[k]) {
                isThisElemExist = true;
            }
        }
        if (!isThisElemExist)
            return false;
    }
    return true;
}

尽管这有很多答案,但我相信这会有所帮助:

const newArray = [ ...new Set( [...arr1, ...arr2] ) ]

这个问题中没有说明数组的结构是什么样子的,所以如果你确定你的数组中既没有嵌套的数组也没有对象(这发生在我身上,这就是我得到这个答案的原因),上面的代码就会起作用。

发生的情况是,我们使用扩展运算符(…)将两个数组合并,然后使用Set消除任何重复。一旦你有了这些,你就可以比较它们的大小,如果三个数组都有相同的大小,那么你就可以去做了。

这个答案也忽略了元素的顺序,正如我所说的,确切的情况发生在我身上,所以也许有人在同样的情况下会在这里结束(正如我所做的那样)。


编辑1。

回答德米特里·格林科的问题:“你为什么在这里使用扩展运算符(…)-……新设置?它不起作用”

考虑以下代码:

const arr1 = [ 'a', 'b' ]
const arr2 = [ 'a', 'b', 'c' ]
const newArray = [ new Set( [...arr1, ...arr2] ) ]
console.log(newArray)

你会得到

[ Set { 'a', 'b', 'c' } ]

为了使用该值,您需要使用一些Set财产(请参见https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set).另一方面,当您使用此代码时:

const arr1 = [ 'a', 'b' ]
const arr2 = [ 'a', 'b', 'c' ]
const newArray = [ ...new Set( [...arr1, ...arr2] ) ]
console.log(newArray)

你会得到

[ 'a', 'b', 'c' ]

这就是区别,前者会给我一个集合,它也会工作,因为我可以得到集合的大小,但后者给了我所需的数组,更直接的是分辨率。

与JSON.encode相同的行是使用join()。

function checkArrays( arrA, arrB ){

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


    //slice so we do not effect the original
    //sort makes sure they are in order
    //join makes it a string so we can do a string compare
    var cA = arrA.slice().sort().join(","); 
    var cB = arrB.slice().sort().join(",");

    return cA===cB;

}

var a = [1,2,3,4,5];
var b = [5,4,3,2,1];
var c = [1,2,3,4];
var d = [1,2,3,4,6];
var e = ["1","2","3","4","5"];  //will return true

console.log( checkArrays(a,b) );  //true
console.log( checkArrays(a,c) );  //false
console.log( checkArrays(a,d) );  //false
console.log( checkArrays(a,e) );  //true

唯一的问题是,如果您关心上次比较测试的类型。如果你关心类型,你将不得不循环。

function checkArrays( arrA, arrB ){

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

    //slice so we do not effect the orginal
    //sort makes sure they are in order
    var cA = arrA.slice().sort(); 
    var cB = arrB.slice().sort();

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

    return true;

}

var a = [1,2,3,4,5];
var b = [5,4,3,2,1];
var c = [1,2,3,4];
var d = [1,2,3,4,6];
var e = ["1","2","3","4","5"];

console.log( checkArrays(a,b) );  //true
console.log( checkArrays(a,c) );  //false
console.log( checkArrays(a,d) );  //false
console.log( checkArrays(a,e) );  //false

如果顺序应该保持不变,而不是循环,则不需要排序。

function checkArrays( 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;

}

var a = [1,2,3,4,5];
var b = [5,4,3,2,1];
var c = [1,2,3,4];
var d = [1,2,3,4,6];
var e = ["1","2","3","4","5"];

console.log( checkArrays(a,a) );  //true
console.log( checkArrays(a,b) );  //false
console.log( checkArrays(a,c) );  //false
console.log( checkArrays(a,d) );  //false
console.log( checkArrays(a,e) );  //false
var er = [{id:"23",name:"23222"}, {id:"222",name:"23222222"}];
var er2 = [{id:"23",name:"23222"}, {id:"222",name:"23222222"}];

var result = (JSON.stringify(er) == JSON.stringify(er2)); // true

如果不更改每个条目的属性顺序,那么它可以很好地处理json对象。

var er = [{name:"23222",id:"23"}, {id:"222",name:"23222222"}];
var er2 = [{id:"23",name:"23222"}, {id:"222",name:"23222222"}];

var result = (JSON.stringify(er) == JSON.stringify(er2)); // false  

但是数组的每个条目中只有一个属性或值,这将很好地工作。