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

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


当前回答

本着原问题的精神:

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

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

而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%的性能提升)。选择最适合您的解决方案,了解每种解决方案的速度和局限性。

其他回答

令人惊讶的是,没有人提出解决办法

const a = [1, 2, 3]
const b = [1, 2, 3, 4]
a.find((v,i) => v !== b[i])

这里的好处是,它不会比较所有值,而是查找第一次出现的值,并尽早结束循环。换句话说,它不是问“两个数组相等吗?”而是问“一个数组与另一个数组不同吗?”。

绩效基准排名第三https://jsben.ch/TgFrA

记住,顺序很重要,a.find(…)!==b.find(…),可以通过a.length==b.length进行检查

if (a.length === b.length && a.find((v,i) => v !== b[i]) === undefined) {
  // equal
}

另一种代码很少的方法(使用Array reduce和Array includes):

arr1.length == arr2.length && arr1.reduce((a, b) => a && arr2.includes(b), true)

如果还要比较顺序的相等性:

arr1.length == arr2.length && arr1.reduce((a, b, i) => a && arr2[i], true)

长度检查确保一个数组中的元素集不仅仅是另一个数组的子集。缩减器用于遍历一个数组并搜索另一个数组中的每个项。如果找不到一项,reduce函数将返回false。在第一个示例中,正在测试是否包含元素第二个示例也检查订单

这是一个字体版本:

//https://stackoverflow.com/a/16436975/2589276
export function arraysEqual<T>(a: Array<T>, b: Array<T>): boolean {
    if (a === b) return true
    if (a == null || b == null) return false
    if (a.length != b.length) return false

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

//https://stackoverflow.com/a/16436975/2589276
export function arraysDeepEqual<T>(a: Array<T>, b: Array<T>): boolean {
    return JSON.stringify(a) === JSON.stringify(b)
}

摩卡的一些测试用例:

it('arraysEqual', function () {
    let a = [1,2]
    let b = [1,2]
    let c = [2,3]
    let d = [2, 3]
    let e = ['car','apple','banana']
    let f = ['car','apple','banana']
    let g = ['car','apple','banan8']

    expect(arraysEqual(a, b)).to.equal(true)
    expect(arraysEqual(c, d)).to.equal(true)
    expect(arraysEqual(a, d)).to.equal(false)
    expect(arraysEqual(e, f)).to.equal(true)
    expect(arraysEqual(f, g)).to.equal(false)
})

it('arraysDeepEqual', function () {
    let a = [1,2]
    let b = [1,2]
    let c = [2,3]
    let d = [2, 3]
    let e = ['car','apple','banana']
    let f = ['car','apple','banana']
    let g = ['car','apple','banan8']
    let h = [[1,2],'apple','banan8']
    let i = [[1,2],'apple','banan8']
    let j = [[1,3],'apple','banan8']

    expect(arraysDeepEqual(a, b)).to.equal(true)
    expect(arraysDeepEqual(c, d)).to.equal(true)
    expect(arraysDeepEqual(a, d)).to.equal(false)
    expect(arraysDeepEqual(e, f)).to.equal(true)
    expect(arraysDeepEqual(f, g)).to.equal(false)
    expect(arraysDeepEqual(h, i)).to.equal(true)
    expect(arraysDeepEqual(h, j)).to.equal(false)
})

与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
let equals = (LHS, RHS) => {
    if (!(LHS instanceof Array)) return "false > L.H.S is't an array";
    if (!(RHS instanceof Array)) return "false > R.H.S is't an array";
    if (LHS.length != RHS.length) return false;
    let to_string = x => JSON.stringify(x.sort((a, b) => a - b));
    return to_string(LHS) == to_string(RHS);
  };

let l = console.log
l(equals([5,3,2],[3,2,5]))    // true
l(equals([3,2,5,3],[3,2,5]))  // false