如何在JavaScript中比较数组?

How to compare arrays in JavaScript?

提问人:Julian H. Lam 提问时间:10/20/2011 最后编辑:MulanJulian H. Lam 更新时间:11/9/2023 访问量:1765268

问:

我想比较两个数组......理想情况下,高效。没什么好看的,只要它们相同,如果不是。毫不奇怪,比较运算符似乎不起作用。truefalse

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 编码确实如此,但是有没有更快或“更好”的方法来简单地比较数组,而无需遍历每个值?

JavaScript 数组 JSON

评论

11赞 TJHeuvel 10/20/2011
您可以首先比较它们的长度,如果它们相等,则每个值相等。
75赞 Felix Kling 10/20/2011
是什么让两个数组对你来说相等?相同的元素?元素的顺序相同?仅当数组的元素可以序列化为 JSON 时,编码为 JSON 才有效。如果数组可以包含对象,你会深入到多深?两个对象什么时候“相等”?
92赞 Alex D 3/17/2014
@FelixKling,定义“平等”绝对是一个微妙的话题,但对于从高级语言开始接触 JavaScript 的人来说,没有理由像 .([] == []) == false
9赞 JonnyRaa 8/29/2014
@AlexD,看起来数组使用引用相等,这是您所期望的。如果你做不到这一点,那就太可怕了
7赞 Tomáš Zato 8/30/2014
@AlexD我想不出有一种语言不会发生这种情况。在 C++ 中,您将比较两个指针 - false。在 Java 中,你所做的与在 javascript 中相同。在PHP中,幕后的东西会遍历数组 - 你称PHP为高级语言吗?

答:

17赞 epascarello 10/20/2011 #1

与 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

评论

3赞 Tomáš Zato 3/22/2013
这仅适用于某些数组,对于大型数组会非常慢。
2赞 Tomáš Zato 3/22/2013
生成JSON也是循环的,你只是(或看起来)不知道它。除了循环之外,生成 JSON 还需要更多的内存 - 它在比较之前创建所述数组的 2 个字符串表示。实现 downwote 函数是为了将答案从最好到最差排序。我认为你的答案不是一个好的答案,所以我投了反对票。
2赞 Tomáš Zato 3/22/2013
对不起,我只是说 JSON 而不是 .也许如果你把你的第二个解决方案说成是主要的(因为它是更好的解决方案,尽管对多维数组没有牙齿),我不会这样判断你。到目前为止,我删除了所有将数组转换为字符串的答案。同样,我投票支持所有使用正确方式的人,以防您需要知道。这意味着 @Tim Down 的答案和 Bireys 的答案。.join()
6赞 Doin 10/16/2014
第一个版本失败了:,这不太可能是你想要的!checkArrays([1,2,3] , ["1,2",3]) == true
2赞 Doin 10/17/2014
@epascarello:是的,你可以,但是(除了你建议的非常长的分隔符效率低下之外),这意味着会有边缘情况(数组恰好包含一个字符串,其中有你的分隔符),checkArrays()函数行为不端。如果你对数组的内容有所了解,这可能不是问题(所以你可以选择一个你确定不会出现在数组项中的分隔符),但是如果你试图编写一个通用的数组比较函数,那么这样使用会使它有微妙的错误!join()
67赞 Tim Down 10/20/2011 #2

目前还不清楚你说的“相同”是什么意思。例如,数组和下面的数组是否相同(注意嵌套数组)?ab

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

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

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

评论

0赞 Tim Down 9/4/2014
@ASDF:从这个问题中不清楚“相同”是什么意思。显然,这个答案只是做了一个肤浅的检查。我会添加一个注释。
0赞 Gopinath Shiva 7/31/2015
对于 arraysIdentical([1, 2, [3, 2]],[1, 2, [3, 2]]);
4赞 Tim Down 8/1/2015
@GopinathShiva:好吧,只有当你期望它返回时,它才会失败。答案解释说不会。如果需要比较嵌套数组,可以轻松添加递归检查。true
1068赞 Tomáš Zato 2/13/2013 #3

要比较数组,请遍历它们并比较每个值:

比较数组:

// Warn if overriding existing method
if(Array.prototype.equals)
    console.warn("Overriding existing Array.prototype.equals. Possible causes: New API defines the method, there's a framework conflict or you've got double inclusions in your code.");
// attach the .equals method to Array's prototype to call it on any array
Array.prototype.equals = function (array) {
    // if the other array is a falsy value, return
    if (!array)
        return false;
    // if the argument is the same array, we can be sure the contents are same as well
    if(array === this)
        return true;
    // compare lengths - can save a lot of time 
    if (this.length != array.length)
        return false;

    for (var i = 0, l=this.length; i < l; i++) {
        // Check if we have nested arrays
        if (this[i] instanceof Array && array[i] instanceof Array) {
            // recurse into the nested arrays
            if (!this[i].equals(array[i]))
                return false;       
        }           
        else if (this[i] != array[i]) { 
            // Warning - two different object instances will never be equal: {x:20} != {x:20}
            return false;   
        }           
    }       
    return true;
}
// Hide method from for-in loops
Object.defineProperty(Array.prototype, "equals", {enumerable: false});

用法:

[1, 2, [3, 4]].equals([1, 2, [3, 2]]) === false;
[1, "2,3"].equals([1, 2, 3]) === false;
[1, 2, [3, 4]].equals([1, 2, [3, 4]]) === true;
[1, 2, 1, 2].equals([1, 2, 1, 2]) === true;

你可能会说“但是比较字符串要快得多 - 没有循环......”好吧,那么你应该注意有循环。第一个递归循环,将 Array 转换为字符串,第二个循环,比较两个字符串。所以这种方法比使用字符串更快

我认为,大量的数据应该始终存储在数组中,而不是存储在对象中。但是,如果您使用对象,也可以对它们进行部分比较。
方法如下:

比较对象:

我在上面已经说过,两个对象实例永远不会相等,即使它们目前包含相同的数据:

({a:1, foo:"bar", numberOfTheBeast: 666}) == ({a:1, foo:"bar", numberOfTheBeast: 666})  //false

这是有原因的,因为例如对象中可能存在私有变量。

但是,如果仅使用对象结构来包含数据,则仍然可以进行比较:

Object.prototype.equals = function(object2) {
    //For the first loop, we only check for types
    for (propName in this) {
        //Check for inherited methods and properties - like .equals itself
        //https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwnProperty
        //Return false if the return value is different
        if (this.hasOwnProperty(propName) != object2.hasOwnProperty(propName)) {
            return false;
        }
        //Check instance type
        else if (typeof this[propName] != typeof object2[propName]) {
            //Different types => not equal
            return false;
        }
    }
    //Now a deeper check using other objects property names
    for(propName in object2) {
        //We must check instances anyway, there may be a property that only exists in object2
            //I wonder, if remembering the checked values from the first loop would be faster or not 
        if (this.hasOwnProperty(propName) != object2.hasOwnProperty(propName)) {
            return false;
        }
        else if (typeof this[propName] != typeof object2[propName]) {
            return false;
        }
        //If the property is inherited, do not check any more (it must be equa if both objects inherit it)
        if(!this.hasOwnProperty(propName))
          continue;
        
        //Now the detail check and recursion
        
        //This returns the script back to the array comparing
        /**REQUIRES Array.equals**/
        if (this[propName] instanceof Array && object2[propName] instanceof Array) {
                   // recurse into the nested arrays
           if (!this[propName].equals(object2[propName]))
                        return false;
        }
        else if (this[propName] instanceof Object && object2[propName] instanceof Object) {
                   // recurse into another objects
                   //console.log("Recursing to compare ", this[propName],"with",object2[propName], " both named \""+propName+"\"");
           if (!this[propName].equals(object2[propName]))
                        return false;
        }
        //Normal value comparison for strings and numbers
        else if(this[propName] != object2[propName]) {
           return false;
        }
    }
    //If everything passed, let's say YES
    return true;
}  

但是,请记住,这是用于比较 JSON 等数据,而不是类实例和其他东西。如果你想比较更复杂的对象,看看这个答案,它是超长函数
要使它工作,您必须稍微编辑原始函数:
Array.equals

...
    // Check if we have nested arrays
    if (this[i] instanceof Array && array[i] instanceof Array) {
        // recurse into the nested arrays
        if (!this[i].equals(array[i]))
            return false;
    }
    /**REQUIRES OBJECT COMPARE**/
    else if (this[i] instanceof Object && array[i] instanceof Object) {
        // recurse into another objects
        //console.log("Recursing to compare ", this[propName],"with",object2[propName], " both named \""+propName+"\"");
        if (!this[i].equals(array[i]))
            return false;
        }
    else if (this[i] != array[i]) {
...

为这两个功能做了一个小测试工具

奖励:带有 和 的嵌套数组indexOfcontains

Samy Bencherif 为您在嵌套数组中搜索特定对象的情况准备了有用的函数,这些函数可在此处获得: https://jsfiddle.net/SamyBencherif/8352y6yw/

评论

36赞 Tim S. 5/15/2013
如果要进行严格的比较,请使用 .this[i] !== array[i]!=
42赞 Oliver 5/31/2013
应调用您的方法而不是 。至少在 .NET 中,compare 通常会返回一个有符号的 int,指示哪个对象大于另一个对象。请参阅:Comparer.Compareequalscompare
17赞 Tolga E 10/17/2013
这不仅是正确的方法,而且效率也更高。这是我为这个问题中建议的所有方法准备的一个快速 jsperf 脚本。jsperf.com/comparing-arrays2
135赞 Jasper 8/14/2014
更改内置类型的原型绝对不是正确的方法
43赞 Jasper 9/1/2014
此外,这不是关于它是否容易重写,而是关于一个答案不应该推荐被认为是不好的做法(developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/...)并且绝对不应该在标题“正确的方法”下方这样做
15赞 yesnik 3/18/2013 #4

就我而言,比较数组仅包含数字和字符串。此函数将显示数组是否包含相同的元素。

function are_arrs_match(arr1, arr2){
    return arr1.sort().toString() === arr2.sort().toString()
}

让我们来测试一下吧!

arr1 = [1, 2, 3, 'nik']
arr2 = ['nik', 3, 1, 2]
arr3 = [1, 2, 5]

console.log (are_arrs_match(arr1, arr2)) //true
console.log (are_arrs_match(arr1, arr3)) //false

评论

0赞 Tim has moved to Codidact 8/3/2016
该问题不要求您进行排序,因此对于例如,您的解决方案是错误的。此外,请参阅本页上的其他讨论,了解为什么字符串化是不必要的、脆弱的和错误的。are_arrs_equal([1,2], [2,1])
0赞 yesnik 8/8/2016
are_arrs_equal([1,2], [2,1])按预期返回。也许这个解决方案并不理想,但它对我有用。true
0赞 Tim has moved to Codidact 8/10/2016
这正是问题所在,对于有序数据结构来说,这两者在任何理智意义上的“相等”都是不相等的。它们是数组,而不是集合,如果你想要集合相等,你应该这样称呼它——并回答一个不同的问题。:-)
2赞 tomazahlin 10/15/2016
我同意上面的评论,但这个解决方案在我的简单整数数组中也适用于我,其中顺序并不重要,所以我会使用它。
1赞 try-catch-finally 7/15/2017
失败(返回)。请注意,call 将修改输入数组 - 这可能不可取。are_arrs_match([1,2], ["1,2"])truethe sort()
3赞 Harry 4/10/2013 #5

Herer 是我的解决方案:

/**
 * Tests two data structures for equality
 * @param {object} x
 * @param {object} y
 * @returns {boolean}
 */
var equal = function(x, y) {
    if (typeof x !== typeof y) return false;
    if (x instanceof Array && y instanceof Array && x.length !== y.length) return false;
    if (typeof x === 'object') {
        for (var p in x) if (x.hasOwnProperty(p)) {
            if (typeof x[p] === 'function' && typeof y[p] === 'function') continue;
            if (x[p] instanceof Array && y[p] instanceof Array && x[p].length !== y[p].length) return false;
            if (typeof x[p] !== typeof y[p]) return false;
            if (typeof x[p] === 'object' && typeof y[p] === 'object') { if (!equal(x[p], y[p])) return false; } else
            if (x[p] !== y[p]) return false;
        }
    } else return x === y;
    return true;
};

适用于任何嵌套数据结构,并且显然忽略了对象的方法。甚至不要考虑用这种方法扩展 Object.prototype,当我尝试过一次时,jQuery 破坏了;)

对于大多数阵列来说,它仍然比大多数序列化解决方案更快。对于对象记录数组,这可能是最快的比较方法。

评论

0赞 kristianlm 2/3/2017
白搭!这些给出了 true: 并且这个错误出来了:equal({}, {a:1})equal({}, null)equal({a:2}, null)
2赞 Igor S. 6/5/2013 #6

扩展托马斯·扎托(Tomáš Zato)的想法。Tomas 的 Array.prototype.compare 实际上应该称为 Array.prototype.compareIdentical。

它传递:

[1, 2, [3, 4]].compareIdentical ([1, 2, [3, 2]]) === false;
[1, "2,3"].compareIdentical ([1, 2, 3]) === false;
[1, 2, [3, 4]].compareIdentical ([1, 2, [3, 4]]) === true;
[1, 2, 1, 2].compareIdentical ([1, 2, 1, 2]) === true;

但在以下方面失败:

[[1, 2, [3, 2]],1, 2, [3, 2]].compareIdentical([1, 2, [3, 2],[1, 2, [3, 2]]])

这是更好的(在我看来)版本:

Array.prototype.compare = function (array) {
    // if the other array is a falsy value, return
    if (!array)
        return false;

    // compare lengths - can save a lot of time
    if (this.length != array.length)
        return false;

    this.sort();
    array.sort();
    for (var i = 0; i < this.length; i++) {
        // Check if we have nested arrays
        if (this[i] instanceof Array && array[i] instanceof Array) {
            // recurse into the nested arrays
            if (!this[i].compare(array[i]))
                return false;
        }
        else if (this[i] != array[i]) {
            // Warning - two different object instances will never be equal: {x:20} != {x:20}
            return false;
        }
    }
    return true;
}

http://jsfiddle.net/igos/bcfCY/

评论

2赞 Mark Amery 6/8/2013
-1.如果它在你给出的例子中“失败”,那么这只是对“失败”的任意定义的情况。为什么你认为这两个不同的数组被认为是相等的?你甚至没有解释你在这里试图实现什么“平等”的概念,或者为什么它是一个明智或有用的概念,但看起来你希望对多维数组进行比较,就好像它们被折叠为一维数组一样。如果是这样,你甚至没有实现这一点:[1,2].compare([[1,2]]) 给你的版本给出了 false,就像 Tomáš 的版本一样。
0赞 Gautham Badhrinathan 7/3/2013
根据我的推断,他说 [1, 2, 3, 4] 和 [1, 3, 2, 4] 应该比较为相等(顺序无关紧要)。
30赞 Evan Steinkerchner 8/1/2013 #7

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

-1赞 user1877408 10/20/2013 #8

我的解决方案比较的是对象,而不是数组。这与 Tomáš 的工作方式相同,因为数组是对象,但没有警告:

Object.prototype.compare_to = function(comparable){
    
    // Is the value being compared an object
    if(comparable instanceof Object){
        
        // Count the amount of properties in @comparable
        var count_of_comparable = 0;
        for(p in comparable) count_of_comparable++;
        
        // Loop through all the properties in @this
        for(property in this){
            
            // Decrements once for every property in @this
            count_of_comparable--;
            
            // Prevents an infinite loop
            if(property != "compare_to"){
                
                // Is the property in @comparable
                if(property in comparable){
                    
                    // Is the property also an Object
                    if(this[property] instanceof Object){
                        
                        // Compare the properties if yes
                        if(!(this[property].compare_to(comparable[property]))){
                            
                            // Return false if the Object properties don't match
                            return false;
                        }
                    // Are the values unequal
                    } else if(this[property] !== comparable[property]){
                        
                        // Return false if they are unequal
                        return false;
                    }
                } else {
                
                    // Return false if the property is not in the object being compared
                    return false;
                }
            }
        }
    } else {
        
        // Return false if the value is anything other than an object
        return false;
    }
    
    // Return true if their are as many properties in the comparable object as @this
    return count_of_comparable == 0;
}
628赞 user2782196 11/3/2013 #9

虽然这仅适用于标量数组(请参阅下面的注释),但它是短代码:

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])

(注意:此处的“标量”是指可以使用 直接比较的值。所以:数字、字符串、引用对象、引用函数。有关比较运算符的更多信息,请参阅 MDN 参考)。===

更新

从我在评论中读到的内容来看,对数组进行排序和比较可能会给出准确的结果:

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

例如:

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

然后上面的代码将返回true

评论

25赞 Ellen Spertus 12/15/2013
我喜欢这个,尽管读者应该知道这仅适用于排序数组。
24赞 Michał Miszczyszyn 3/24/2016
它适用于任何类型的数组,排序或不排序@espertus
53赞 Michał Miszczyszyn 3/26/2016
是的,没错。这个函数应该比较两个数组,无论它们是否排序,它们的连续元素必须相等。
33赞 Quentin Roy 6/6/2016
@espertus 事实上,如果元素在两个数组中的顺序不完全相同,则不会返回 true。但是,相等性检查的目标不是检查它们是否包含相同的元素,而是检查它们是否具有相同顺序的相同元素。
12赞 mems 11/21/2016
如果要检查两个数组是否相等,包含相同的未排序项(但未多次使用),可以使用:(不会按预期工作)a1.length==a2.length && a1.every((v,i)=>a2.includes(v))var a1 =[1,2,3], a2 = [3,2,1];var a1 =[1,3,3], a2 = [1,1,3];
294赞 Jason Boerner 2/3/2014 #10

我喜欢将 Underscore 库用于数组/对象繁重的编码项目......在下划线和 Lodash 中,无论您是比较数组还是对象,它看起来都是这样的:

_.isEqual(array1, array2)   // returns a boolean
_.isEqual(object1, object2) // returns a boolean

评论

39赞 Vitalii Alekask 8/18/2015
请注意,顺序很重要_.isEqual([1,2,3], [2,1,3]) => false
4赞 hellatan 2/18/2016
或者,如果您只想要功能,则始终可以使用 lodash.isequal 模块isEqual
10赞 Ronan Quillevere 3/31/2017
你也许可以使用 _.difference();如果订单对您无关紧要
16赞 filype 6/2/2017
我们可以在此检查之前对数组进行排序,如果顺序无关紧要_.isEqual([1,2,3].sort(), [2,1,3].sort()) => true
0赞 Mike D3ViD Tyson 5/14/2020
在 React.js 中抛出异常:“_”未定义
-2赞 Martin 4/14/2014 #11

这里有一个 CoffeeScript 版本,适合那些喜欢它的人:

Array.prototype.equals = (array) ->
  return false if not array # if the other array is a falsy value, return
  return false if @length isnt array.length # compare lengths - can save a lot of time

  for item, index in @
    if item instanceof Array and array[index] instanceof Array # Check if we have nested arrays
      if not item.equals(array[index]) # recurse into the nested arrays
        return false
    else if this[index] != array[index]
      return false # Warning - two different object instances will never be equal: {x:20} != {x:20}
  true

所有功劳都归@tomas-zato所有。

-1赞 Serge 4/18/2014 #12

如果数组是普通的,顺序很重要,那么这两行可能会有所帮助

//Assume
var a = ['a','b', 'c']; var b = ['a','e', 'c'];  

if(a.length !== b.length) return false;
return !a.reduce(
  function(prev,next,idx, arr){ return prev || next != b[idx] },false
); 

Reduce遍历其中一个数组,如果“a”的至少一个元素不等同于“b”的元素,则返回“false” 只需将其包装到函数中即可

评论

0赞 Thoran 7/16/2016
映射、减少、过滤一切!:P
1赞 Mulan 8/7/2016
这是一个糟糕的解决方案,因为即使第一个比较的元素不匹配,也会遍历每个元素。此外,在循环中使用 and 是双重否定,这使得这个答案比它需要的更复杂(并且难以阅读)Array.prototype.reducea!a!=
0赞 Serge 8/8/2016
同意。有一些 some() 函数:)两年前,我不知道。但双重否定仍然存在。
237赞 radtek 5/9/2014 #13

我认为这是使用 JSON stringify 执行此操作的最简单方法,在某些情况下它可能是最佳解决方案:

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

这会将对象转换为字符串,以便可以进行比较。在大多数情况下,顺序很重要,因为它可以使用上述答案之一中所示的排序算法对对象进行排序。a1a2

请注意,您不再比较对象,而是比较对象的字符串表示形式。它可能不完全是你想要的。

评论

5赞 radtek 1/18/2016
@PardeepJain,这是因为默认情况下,当对象的 ECMAScript 中的相等运算符引用相同的内存位置时,它们将返回 true。尝试 var x = y = [];现在,相等返回 true。
14赞 Lukas Liesis 4/29/2017
只是要注意 JSON stringify 函数并不快。与较大的数组一起使用肯定会引入延迟。
21赞 Don Hatch 5/10/2017
这个问题特别询问是否有比使用 JSON.stringify 更好/更快的方法。
2赞 radtek 5/12/2017
它更详细地解释了为什么在某些情况下这可能是一个很好的解决方案。
2赞 Mars Robertson 3/2/2019
老实说,起初我没有注意到原始问题提到 - 对于简单的用例,感觉最简单......JSON.stringify()
0赞 Omar Elawady 4/6/2015 #14

此脚本比较对象、数组和多维数组

function compare(a,b){
     var primitive=['string','number','boolean'];
     if(primitive.indexOf(typeof a)!==-1 && primitive.indexOf(typeof a)===primitive.indexOf(typeof b))return a===b;
     if(typeof a!==typeof b || a.length!==b.length)return false;
     for(i in a){
          if(!compare(a[i],b[i]))return false;
     }
     return true;
}

第一行检查它是否为基元类型。如果是这样,它将比较这两个参数。

如果它们是对象。它遍历 Object 并以递归方式检查每个元素。

用法:

var a=[1,2,[1,2]];
var b=[1,2,[1,2]];
var isEqual=compare(a,b);  //true
0赞 chessweb 4/18/2015 #15

此函数比较任意形状和尺寸的两个数组:

function equals(a1, a2) {

    if (!Array.isArray(a1) || !Array.isArray(a2)) {
        throw new Error("Arguments to function equals(a1, a2) must be arrays.");
    }

    if (a1.length !== a2.length) {
        return false;
    }

    for (var i=0; i<a1.length; i++) {
        if (Array.isArray(a1[i]) && Array.isArray(a2[i])) {
            if (equals(a1[i], a2[i])) {
                continue;
            } else {
                return false;
            }
        } else {
            if (a1[i] !== a2[i]) {
                return false;
            }
        }
    }

    return true;
}
6赞 metakermit 6/10/2015 #16

如果您使用像 Mocha 这样的测试框架和 Chai 断言库,则可以使用深度相等来比较数组。

expect(a1).to.deep.equal(a2)

仅当数组在相应索引处具有相等的元素时,才应返回 true。

4赞 peonicles 11/11/2015 #17

我们可以通过功能方式做到这一点,使用 (https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/everyevery)

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

评论

0赞 Ankit Kumar 6/28/2022
如果我们想要 arr1 == arr2,如果 arr1 的所有数据都在 arr2 中,反之亦然,则不起作用,以什么顺序排列并不重要。
89赞 Mulan 12/14/2015 #18

实用的方法

我认为,如果一个特定的实现只是“正确的”(“正确”),而不是一个“错误”的解决方案,那么说它是“正确的方式™”是错误的。Tomáš 的解决方案比基于字符串的数组比较有了明显的改进,但这并不意味着它在客观上是“正确的”。到底什么是的?它是最快的吗?它是最灵活的吗?它是最容易理解的吗?它是最快的调试吗?它是否使用最少的操作?它有任何副作用吗?没有一个解决方案可以拥有最好的东西。

托马斯可以说他的解决方案很快,但我也会说这是不必要的复杂。它试图成为一个多合一的解决方案,适用于所有阵列,无论是否嵌套。事实上,它甚至接受的不仅仅是数组作为输入,并且仍然试图给出一个“有效”的答案。


泛型提供可重用性

我的答案会以不同的方式处理这个问题。我将从一个只与单步执行数组有关的通用过程开始。从那里,我们将构建其他基本比较函数,如 和 等arrayComparearrayEqualarrayDeepEqual

// arrayCompare :: (a -> a -> Bool) -> [a] -> [a] -> Bool
const arrayCompare = f => ([x,...xs]) => ([y,...ys]) =>
  x === undefined && y === undefined
    ? true
    : Boolean (f (x) (y)) && arrayCompare (f) (xs) (ys)

在我看来,最好的代码甚至不需要注释,这也不例外。这里几乎没有发生什么,以至于您几乎可以毫不费力地理解此过程的行为。当然,有些 ES6 语法现在对你来说可能看起来很陌生,但这只是因为 ES6 相对较新。

如类型所示,采用比较函数 、 和两个输入数组,以及 。在大多数情况下,我们所做的只是调用输入数组中的每个元素。如果用户定义的返回,我们会提前返回 - 这要归功于 的短路评估。所以是的,这意味着比较器可以提前停止迭代,并防止在不必要时遍历输入数组的其余部分。arrayComparefxsysf (x) (y)falseffalse&&


严格比较

接下来,使用我们的函数,我们可以轻松创建我们可能需要的其他函数。我们将从初级开始......arrayComparearrayEqual

// equal :: a -> a -> Bool
const equal = x => y =>
  x === y // notice: triple equal

// arrayEqual :: [a] -> [a] -> Bool
const arrayEqual =
  arrayCompare (equal)

const xs = [1,2,3]
const ys = [1,2,3]
console.log (arrayEqual (xs) (ys))      //=> true
// (1 === 1) && (2 === 2) && (3 === 3)  //=> true

const zs = ['1','2','3']
console.log (arrayEqual (xs) (zs))      //=> false
// (1 === '1')                          //=> false

就这么简单。 可以用比较器函数定义,该函数与使用进行比较(用于严格相等)。arrayEqualarrayCompareab===

请注意,我们还将它自己的函数定义为它自己的函数。这突出了作为高阶函数在另一种数据类型(Array)的上下文中使用一阶比较器的作用。equalarrayCompare


松散的比较

我们可以很容易地使用 代替 来定义。现在,当将 (Number) 与 (String) 进行比较时,结果将是......arrayLooseEqual==1'1'true

// looseEqual :: a -> a -> Bool
const looseEqual = x => y =>
  x == y // notice: double equal

// arrayLooseEqual :: [a] -> [a] -> Bool
const arrayLooseEqual =
  arrayCompare (looseEqual)

const xs = [1,2,3]
const ys = ['1','2','3']
console.log (arrayLooseEqual (xs) (ys))    //=> true
// (1 == '1') && (2 == '2') && (3 == '3')  //=> true

深度比较(递归)

您可能已经注意到,这只是肤浅的比较。当然,托马斯的解决方案是“正确的方法™”,因为它确实隐含了深度比较,对吧?

好吧,我们的程序用途广泛,可以使深度相等性测试变得轻而易举......arrayCompare

// isArray :: a -> Bool
const isArray =
  Array.isArray

// arrayDeepCompare :: (a -> a -> Bool) -> [a] -> [a] -> Bool
const arrayDeepCompare = f =>
  arrayCompare (a => b =>
    isArray (a) && isArray (b)
      ? arrayDeepCompare (f) (a) (b)
      : f (a) (b))

const xs = [1,[2,[3]]]
const ys = [1,[2,['3']]]
console.log (arrayDeepCompare (equal) (xs) (ys)) //=> false
// (1 === 1) && (2 === 2) && (3 === '3')         //=> false

console.log (arrayDeepCompare (looseEqual) (xs) (ys)) //=> true
// (1 == 1) && (2 == 2) && (3 == '3')                 //=> true

就这么简单。我们使用另一个高阶函数构建一个深度比较器。这一次,我们使用自定义比较器进行包装,该比较器将检查是否和是否是数组。如果是这样,请重新应用,否则与用户指定的比较器 () 进行比较。这使我们能够将深度比较行为与实际比较单个元素的方式分开。也就是说,如上例所示,我们可以使用 、 或我们制作的任何其他比较器进行深度比较。arrayCompareabarrayDeepCompareabfequallooseEqual

因为是咖喱,我们也可以像前面的例子一样部分应用它arrayDeepCompare

// arrayDeepEqual :: [a] -> [a] -> Bool
const arrayDeepEqual =
  arrayDeepCompare (equal)

// arrayDeepLooseEqual :: [a] -> [a] -> Bool
const arrayDeepLooseEqual =
  arrayDeepCompare (looseEqual)

对我来说,这已经比 Tomáš 的解决方案有了明显的改进,因为我可以根据需要为我的阵列明确选择浅层或深度比较。


对象比较(示例)

现在,如果你有一个对象数组或其他东西怎么办?如果每个对象具有相同的值,也许您想将这些数组视为“相等”......id

// idEqual :: {id: Number} -> {id: Number} -> Bool
const idEqual = x => y =>
  x.id !== undefined && x.id === y.id

// arrayIdEqual :: [a] -> [a] -> Bool
const arrayIdEqual =
  arrayCompare (idEqual)

const xs = [{id:1}, {id:2}]
const ys = [{id:1}, {id:2}]
console.log (arrayIdEqual (xs) (ys)) //=> true
// (1 === 1) && (2 === 2)            //=> true

const zs = [{id:1}, {id:6}]
console.log (arrayIdEqual (xs) (zs)) //=> false
// (1 === 1) && (2 === 6)            //=> false

就这么简单。在这里,我使用了普通的 JS 对象,但这种类型的比较器可以适用于任何对象类型;甚至是您的自定义对象。托马斯的解决方案需要完全重新设计,以支持这种相等性测试

带有对象的深度阵列?没问题。我们构建了高度通用的通用函数,因此它们可以在各种用例中工作。

const xs = [{id:1}, [{id:2}]]
const ys = [{id:1}, [{id:2}]]
console.log (arrayCompare (idEqual) (xs) (ys))     //=> false
console.log (arrayDeepCompare (idEqual) (xs) (ys)) //=> true

任意比较(示例)

或者,如果你想做一些其他类型的完全任意的比较呢?也许我想知道每个是否都大于每个......xy

// gt :: Number -> Number -> Bool
const gt = x => y =>
  x > y

// arrayGt :: [a] -> [a] -> Bool
const arrayGt = arrayCompare (gt)

const xs = [5,10,20]
const ys = [2,4,8]
console.log (arrayGt (xs) (ys))     //=> true
// (5 > 2) && (10 > 4) && (20 > 8)  //=> true

const zs = [6,12,24]
console.log (arrayGt (xs) (zs))     //=> false
// (5 > 6)                          //=> false

少即是多

你可以看到,我们实际上是在用更少的代码做更多的事情。它本身并不复杂,我们制作的每个自定义比较器都有一个非常简单的实现。arrayCompare

我们可以很容易地准确地定义我们希望如何比较两个数组——浅层、深层、严格、松散、某些对象属性或一些任意计算,或这些数组的任意组合——所有这些都使用一个过程 .甚至可能想出一个比较器!我知道孩子们是多么喜欢那些正则表达式......arrayCompareRegExp

它是最快的吗?不。但可能也不需要。如果速度是衡量代码质量的唯一指标,那么很多真正优秀的代码就会被扔掉——这就是为什么我把这种方法称为“实用方法”。或者更公平地说,一种实用的方法。这个描述适合这个答案,因为我并不是说这个答案只是与其他一些答案相比才实用;这是客观真实的。我们已经用很少的代码实现了高度的实用性,这很容易推理。没有其他代码可以说我们没有获得此描述。

这是否使它成为适合您的“正确”解决方案?这由决定。没有其他人能为你做到这一点;只有您知道自己的需求是什么。在几乎所有情况下,我都看重简单、实用和通用的代码,而不是聪明和快速的代码。你看重的东西可能会有所不同,所以选择适合你的。


编辑

我以前的答案更侧重于分解成微小的程序。这是一个有趣的练习,但并不是解决这个问题的最佳(最实用)方法。如果您有兴趣,可以查看此修订历史记录。arrayEqual

评论

14赞 Don Hatch 5/10/2017
“最好的代码甚至不需要注释”......不想这么说,但这段代码可以使用更多的注释和/或不同的名称——“比较”非常模糊。如果我没看错的话,你的“比较”本质上是一个咖喱递归的“每一个”。我认为。还是咖喱递归“一些”?嗯。这需要比必要的更多的思考。也许更好的名称是“arraysEquivalent”,利用“等价关系”的标准术语。或者,更清楚(无论如何对我来说),“递归等效”。
1赞 Mulan 5/10/2017
@DonHatch感谢您有机会回复。你说的“比较”是什么意思?是的,该函数是咖喱的,但它与 和 不同。 需要一个比较器和两个数组进行比较。我选择了一个特别通用的名称,因为我们可以使用任意函数比较数组。该函数是Curried的,因此可以专门用于创建新的数组比较函数(例如,)。你能建议一个更好的名字吗?您认为哪些方面需要额外的评论或解释?我很乐意讨论 ^_^arrayComparesomeeveryarrayComparearrayEqual
1赞 Don Hatch 5/10/2017
不确定我的观点是否很清楚——但我的观点是,你的函数并不是真的打算接受任意函数,我不认为——它打算接受一个等价关系,它返回一个等价关系。这很重要——如果像我提到的那些其他类型的任意二进制函数,即使是人们经常称之为“比较”的函数,它也不会做任何明智的事情(我不认为)。因此,我认为在名称中加上“等效”代替“比较”会有所帮助。
1赞 whitneyland 11/23/2017
@ftor,作者:超级有用的答案,干得好,+1。反馈:您提倡简单,但对于许多开发人员来说,一行上有三个箭头的表达式并不简单或易于理解。例如:f=> ([x,...xs]) => ([y,...ys]) =>。我经常使用它,但仍然不得不在精神上分解它,而不是“只是看着它”。第二点是正确的,使用每一个。即使权衡你的理由,总的来说,这不仅在我看来更好,而且从你的角度来看,当试图推断你的设计理念时。
2赞 Mulan 11/23/2017
我知道这是一个学习的地方,但我在这里做了一个假设,研究函数式风格的普通程序员可以将任何curried函数转换为uncurried函数。我的回答并不是说这种风格应该在你自己的程序中使用——不加好奇地写它,用你自己的缩进规则写它,随心所欲地写它——我用一种我认为最能表达程序的风格来写我的答案。我还想邀请其他人挑战我们在语法上表达程序的方式
-1赞 Victor Castro 8/31/2016 #19

我会这样做:

[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()

评论

5赞 Mulan 2/19/2017
监督:[1,2,3,4].toString() === ["1,2,3",4].toString() // => true
0赞 Victor Castro 2/20/2017
当你只有一个层次的深度时,最好使用它
5赞 DEls 11/9/2016 #20

另一种代码很少的方法(使用 Array reduceArray 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)
  • 该检查可确保一个数组中的元素集不仅仅是另一个数组的子集。length

  • reducer 用于遍历一个数组并搜索另一个数组中的每个项目。如果未找到一项,则 reduce 函数返回 。false

    1. 在第一个示例中,正在测试是否包含元素
    2. 第二个示例也检查订单

评论

0赞 Ankit Kumar 6/28/2022
如果数组的其中一个元素为 0,则将始终失败。
6赞 Gaizka Allende 2/10/2017 #21

如果它们只是两个数字或字符串数组,这是一个快速的单行数组

const array1 = [1, 2, 3];
const array2 = [1, 3, 4];
console.log(array1.join(',') === array2.join(',')) //false

const array3 = [1, 2, 3];
const array4 = [1, 2, 3];
console.log(array3.join(',') === array4.join(',')) //true

评论

0赞 Dan M. 5/8/2017
常量数组 1 = [1];常量数组 2 = [1, 1];console.log(array1.join('') === array2.join('')) //返回 true
0赞 Gaizka Allende 5/9/2017
它不应该:array1.join('') 是 '1' 和 array2.join('') 是 '11'
0赞 Dan M. 5/10/2017
对不起,错别字。第一个数组应为 .关于为什么会发生这种情况以及如何解决,非常明显。[11]
0赞 Gaizka Allende 5/11/2017
不知道你在说什么,这很简单:[1].join() 是 “1” 和 [1,1].join() 是 “1,1”,所以它们永远不会相等
1赞 try-catch-finally 7/15/2017
和 失败。[1,2]["1,2"]
178赞 unitario 2/12/2017 #22

本着原始问题的精神:

我想比较两个数组......理想情况下,高效无 花哨,如果它们相同,则为真,如果不是,则为假。

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

(67%) 由 Tim Down 撰写

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

(69%) 由 User2782196

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

减少 (74%) DEI

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

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

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

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

Victor Palomo 的 half toString (90%)

a1 == a2.toString();

Stringify (100%) 由 Radtek

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

请注意,以下示例假定数组是经过排序的一维数组。 删除了通用基准测试的比较(添加到任何建议中,您将获得 ~10% 的性能提升)。选择最适合您的任何解决方案,了解每种解决方案的速度和局限性。.lengtha1.length === a2.length

第三方编辑

在我看来,jsbench 现在正在从快速 (100%) 到较慢 (例如 11%) 进行排序。代码示例包含一个减速版本。arrEvery()


function arrEvery(a1,a2) 
{
    // user2782196: http://stackoverflow.com/a/19746771/308645
    return a1.every((v,i)=> v === a2[i]);
}

// slowed down
function arrEveryWithSlowDown(a1,a2) 
{
    setTimeout(() => {
        console.log("Slow down pal!");
    }, 1500);
    return a1.every((v,i)=> v === a2[i]);
}

减速版本的百分比较小。括号中的数字可能是运行的赛赛尔/操作的数量。arrEvery

jsbench.ch result array comparison

评论

0赞 Narayon 8/27/2019
如果增加数组大小,则这些数字不适用(尤其是 reduce 方法)。尝试使用 ${v}Array.from({length: 1000}).map((a,v)=> .padStart(10,2));
0赞 KR Tirtho 11/20/2020
应该使用 before & join。例如sort()a1a2a1.sort().join("")===a2.sort().join("")
5赞 Cees Timmerman 11/28/2021
join('')很危险,因为 .我更喜欢.['foo', 'bar'].join('') == ['foobar'].join('')a1 ==''+ a2
16赞 Human programmer 4/6/2022
这些百分比数字到底意味着什么?
3赞 Shawn 12/18/2022
@TheHumanCat我敢肯定,最慢的实现代表了 100%,而其他的则代表了一小部分时间。因此,使用将花费 67% 的时间。这有点类似于面包师的百分比......whilestringify
4赞 Nathan Boolean Trujillo 3/2/2017 #23

这比较了 2 个未排序的数组:

function areEqual(a, b) {
  if ( a.length != b.length) {
    return false;
  }
  return a.filter(function(i) {
    return !b.includes(i);
  }).length === 0;  
}

评论

0赞 user3.1415927 2/6/2020
虽然价格昂贵(就计算资源而言),但这是一个强大的解决方案,应该适用于各种类型,并且不依赖于排序!
0赞 arielhad 12/23/2021
这将无法比较 [1, 1, 2] 和 [2, 2, 1]
2赞 Vasanth 3/8/2017 #24
var a1 = [1,2,3,6];
var a2 = [1,2,3,5];

function check(a, b) {
  return (a.length != b.length) ? false : 
  a.every(function(row, index) {
    return a[index] == b[index];
  });
}  

check(a1, a2);

或///////

var a1 = [1,2,3,6];
var a2 = [1,2,3,6];

function check(a, b) {
  return (a.length != b.length) ? false : 
  !(a.some(function(row, index) {
    return a[index] != b[index];
  }));
}  

check(a1, a2)

评论

0赞 Vasanth 3/8/2017
您也可以使用一些函数,如果我们满足所需的条件,这些函数不会完全迭代,如上所述
-1赞 d9k 5/24/2017 #25

尝试了深度平等,它奏效了

var eq = require('deep-equal');
eq({a: 1, b: 2, c: [3, 4]}, {c: [3, 4], a: 1, b: 2});
15赞 Jeferson Euclides 11/7/2017 #26

尽管这有很多答案,但我认为有一个是有帮助的:

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

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

发生的情况是,我们使用扩展运算符 ( ... ) 来连接两个数组,然后我们使用 Set 来消除任何重复项。一旦你有了它,你就可以比较它们的大小,如果所有三个阵列的大小相同,你就可以开始了。

这个答案也忽略了元素的顺序,正如我所说,确切的情况发生在我身上,所以也许处于相同情况的人可能会在这里结束(就像我一样)。


编辑1.

回答德米特里·格林科(Dmitry Grinko)的问题:“您为什么使用点差运算符(...这里-。。。新 设置 ?它不起作用”

请考虑以下代码:

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' ]

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

评论

0赞 Dmitry Grinko 11/10/2017
你为什么在这里使用点差运算符 ( ... ) - ...新 设置 ?这是行不通的。
0赞 Jeferson Euclides 11/10/2017
德米特里·格林科(Dmitry Grenko):我相信我在我的Edit1上回答了您的问题。但我不确定你说“它不起作用”是什么意思,因为这两个答案都会让你碍手碍脚
1赞 Leo Lei 9/17/2020
[1, 2, 2, 3], [1, 2, 2, 3] <这不就是失败了吗?生成的集合的长度将与输入的长度不同。
0赞 Jeferson Euclides 12/17/2020
@LeoLei你是对的,正如帖子中所解释的,这对于某些情况非常具体。我在比较数据库响应时使用了它,我知道我不会遇到与您提到的类似的情况。
1赞 EigenFool 9/5/2022
好!我一直在沿着这些思路寻找 sth。这应该有更多的选票。点赞
4赞 Pedro Rodrigues 11/19/2017 #27

一个简单的方法:

function equals(a, b) {
    if ((a && !b) || (!a && b) || (!a && !b) || (a.length !== b.length)) {
        return false;
    }

    var isDifferent = a.some(function (element, index) { 
        return element !== b[index];
    });

    return !isDifferent;
}
3赞 Leed 11/25/2017 #28
JSON.stringify(collectionNames).includes(JSON.stringify(sourceNames)) ?  array.push(collection[i]) : null

我就是这样做的。

评论

0赞 Ben Rondeau 12/14/2017
很好的解决方案 - 但我想知道在某些情况下它是否总是按预期工作,例如使用某些基元或深度嵌套数组?我希望它在任何情况下都有效
0赞 LachoTomov 3/21/2018 #29

可以选择比较或不比较顺序:

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;
        }
    });
}
4赞 AL-zami 5/12/2018 #30

已经有一些很好的答案。但我想分享另一个想法,这个想法已被证明在比较阵列时是可靠的。我们可以使用 JSON.stringify ( ) 比较两个数组。它将在数组中创建一个字符串,从而比较从两个数组中获得的两个字符串是否相等

JSON.stringify([1,{a:1},2]) == JSON.stringify([1,{a:1},2]) //true

JSON.stringify([1,{a:1},2]) == JSON.stringify([1,{a:2},2]) //false

JSON.stringify([1,{a:1},2]) == JSON.stringify([1,{a:2},[3,4],2]) //false

JSON.stringify([1,{a:1},[3,4],2]) == JSON.stringify([1,{a:2},[3,4],2]) //false

JSON.stringify([1,{a:2},[3,4],2]) == JSON.stringify([1,{a:2},[3,4],2]) //true

JSON.stringify([1,{a:2},[3,4],2]) == JSON.stringify([1,{a:2},[3,4,[5]],2]) //false

JSON.stringify([1,{a:2},[3,4,[4]],2]) == JSON.stringify([1,{a:2},[3,4,[5]],2]) //false

JSON.stringify([1,{a:2},[3,4,[5]],2]) == JSON.stringify([1,{a:2},[3,4,[5]],2]) //true

评论

0赞 Ankit Kumar 6/28/2022
不起作用是元素的顺序无关紧要。
0赞 AL-zami 6/28/2022
你能详细说明一下吗?
2赞 KANJICODER 6/27/2018 #31

递归 & 适用于 NESTED 数组:

function ArrEQ(a1,a2){
   return( 
        //:Are both elements arrays?
        Array.isArray(a1)&&Array.isArray(a2) 
        ?
        //:Yes: Test each entry for equality:
        a1.every((v,i)=>(ArrEQ(v,a2[i])))
        :
        //:No: Simple Comparison:
        (a1===a2)
   );;
};;

console.log( "Works With Nested Arrays:" );
console.log( ArrEQ( 
    [1,2,3,[4,5,[6,"SAME/IDENTICAL"]]],
    [1,2,3,[4,5,[6,"SAME/IDENTICAL"]]]
));;     
console.log( ArrEQ( 
    [1,2,3,[4,5,[6,"DIFFERENT:APPLES" ]]],
    [1,2,3,[4,5,[6,"DIFFERENT:ORANGES"]]]
));;  
2赞 KANJICODER 6/27/2018 #32

使用带有 NESTED 数组的多个参数:

//:Return true if all of the arrays equal.
//:Works with nested arrays.
function AllArrEQ(...arrays){
    for(var i = 0; i < (arrays.length-1); i++ ){
        var a1 = arrays[i+0];
        var a2 = arrays[i+1];
        var res =( 
            //:Are both elements arrays?
            Array.isArray(a1)&&Array.isArray(a2) 
            ?
            //:Yes: Compare Each Sub-Array:
            //:v==a1[i]
            a1.every((v,i)=>(AllArrEQ(v,a2[i])))
            :
            //:No: Simple Comparison:
            (a1===a2)
        );;
        if(!res){return false;}
    };;
    return( true );
};;

console.log( AllArrEQ( 
        [1,2,3,[4,5,[6,"ALL_EQUAL"   ]]],
        [1,2,3,[4,5,[6,"ALL_EQUAL"   ]]],
        [1,2,3,[4,5,[6,"ALL_EQUAL"   ]]],
        [1,2,3,[4,5,[6,"ALL_EQUAL"   ]]],
));; 
7赞 Esqarrouth 10/8/2018 #33

下面是一个 Typescript 版本:

//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)
})
0赞 Daphoque 5/21/2019 #34

处理数字/字符串/数组/对象的递归 cmp 函数

<script>
var cmp = function(element, target){

   if(typeof element !== typeof target)
   {
      return false;
   }
   else if(typeof element === "object" && (!target || !element))
   {
      return target === element;
   }
   else if(typeof element === "object")
   {
       var keys_element = Object.keys(element);
       var keys_target  = Object.keys(target);
       
       if(keys_element.length !== keys_target.length)
       {
           return false;
       }
       else
       {
           for(var i = 0; i < keys_element.length; i++)
           {
                if(keys_element[i] !== keys_target[i])
                    return false;
                if(!cmp(element[keys_element[i]], target[keys_target[i]]))
                    return false;
           }
		   return true;
       }
   }
   else
   {
   	   return element === target;

   }
};

console.log(cmp({
    key1: 3,
    key2: "string",
    key3: [4, "45", {key4: [5, "6", false, null, {v:1}]}]
}, {
    key1: 3,
    key2: "string",
    key3: [4, "45", {key4: [5, "6", false, null, {v:1}]}]
})); // true

console.log(cmp({
    key1: 3,
    key2: "string",
    key3: [4, "45", {key4: [5, "6", false, null, {v:1}]}]
}, {
    key1: 3,
    key2: "string",
    key3: [4, "45", {key4: [5, "6", undefined, null, {v:1}]}]
})); // false
</script>

1赞 corysimmons 6/2/2019 #35

实际上,在 Lodash 文档中,他们给出了两个很好的例子来比较和返回差异和相似之处的新数组(分别在下面的示例中):

import { differenceWith, intersectionWith, isEqual } from 'lodash'

differenceWith(
  [{ a: 1 }, { b: 1 }],
  [{ a: 1 }, { b: 1 }, { c: 1 }],
  isEqual
) // []... 💀the bigger array needs to go first!

differenceWith(
  [{ a: 1 }, { b: 1 }, { c: 1 }],
  [{ a: 1 }, { b: 1 }],
  isEqual,
) // [{ c: 1 }] 🎉

intersectionWith(
  [{ a: 1 }, { b: 1 }],
  [{ a: 1 }, { b: 1 }, { c: 1 }],
  isEqual,
) // [{ a: 1 }, { b: 1 }] 🎉this one doesn't care about which is bigger

如果你并不总是知道哪个数组会更大,你可以为它编写一个辅助函数,如下所示:

const biggerFirst = (arr1, arr2) => {
  return arr1.length > arr2.length ? [arr1, arr2] : [arr2, arr1]
}

const [big, small] = biggerFirst(
  [{ a: 1 }, { b: 1 }],
  [{ a: 1 }, { b: 1 }, { c: 1 }],
)

differenceWith(big, small, isEqual) // 🎉even though we have no idea which is bigger when they are fed to biggerFirst()

据我所知,这些也非常匹配,所以这很好。

我知道一切都应该依赖库来做事,但这是我发现的解决一个非常常见的问题的最简洁/干净的解决方案。希望它对某人有所帮助!

9赞 Mr. Durga prasad patra 6/24/2019 #36

当两个数组具有相同的元素但顺序不同时,您的代码将无法正确处理大小写。

看看我的代码和你的示例,它比较了两个元素是数字的数组,你可以为其他元素类型修改或扩展它(通过使用 .join() 而不是 .toString())。

var a1 = [1,2,3];
var a2 = [1,2,3];
const arraysAreEqual = a1.sort().toString()==a2.sort().toString();
// true if both arrays have same elements else false
console.log(arraysAreEqual);

4赞 Pedro Bustamante 6/28/2019 #37
In a simple way uning stringify but at same time thinking in complex arrays:

**Simple arrays**:  
var a = [1,2,3,4];  
var b = [4,2,1,4];  
JSON.stringify(a.sort()) === JSON.stringify(b.sort()) // true  

**Complex arrays**:  
var a = [{id:5,name:'as'},{id:2,name:'bes'}];  
var b = [{id:2,name:'bes'},{id:5,name:'as'}];  
JSON.stringify(a.sort(function(a,b) {return a.id - b.id})) === JSON.stringify(b.sort(function(a,b) {return a.id - b.id})) // true  

**Or we can create a sort function**  

function sortX(a,b) {  
return a.id -b.id; //change for the necessary rules  
}  
JSON.stringify(a.sort(sortX)) === JSON.stringify(b.sort(sortX)) // true  
2赞 ArifMustafa 7/16/2019 #38

我相信 plain 和 with ,这是甜蜜而简单易懂的。JSECMAScript 2015

var is_arrays_compare_similar = function (array1, array2) {

    let flag = true;

    if (array1.length == array2.length) {

        // check first array1 object is available in array2 index
        array1.every( array_obj => {
            if (flag) {
                if (!array2.includes(array_obj)) {
                    flag = false;
                }
            }
        });
        
        // then vice versa check array2 object is available in array1 index
        array2.every( array_obj => {
            if (flag) {
                if (!array1.includes(array_obj)) {
                    flag = false;
                }
            }
        });

        return flag;
    } else {
        return false;
    }
    
}

评论

7赞 JeffryHouser 11/3/2019
为什么需要反之亦然的检查?我们知道数组的大小相同,所以如果 array1 中的每个项目也在 array2 中找到;为什么我们必须检查 Array2 中的每个项目是否也在 Array1 中?
0赞 Tommy Grovnes 10/9/2021
第一个数组可以是 [1,1],第二个数组可以是 [1,2],反之亦然,这无法检测到
3赞 undefined 10/10/2019 #39

我知道 JSON.stringfy 在处理大型数据集时很慢,但如果您使用模板文字怎么办?

例:

const a = [1, 2, 3];
const b = [1, 2, 'test'];

const a_string = Array.isArray(a) && `${a}`;
const b_string = Array.isArray(b) && `${b}`;

const result = (a === b);

console.log(result);

当然,考虑到您使用的是 ES6。

=)

评论

0赞 Elias Dorneles 5/2/2020
请注意,与字符串相比,这种比较也适用于数组。
0赞 undefined 5/2/2020
@EliasDorneles,非常感谢!我更新了我的答案,以便在将变量分配给模板字符串文字之前执行检查。
0赞 Elias Dorneles 5/2/2020
呵呵,现在它会说这两个是平等的,(或)......我认为用这种方法很难得到一些健壮的东西。^^a = ["1,1", "2"]b = [1,1,2]b = ["1", "1,2"]
0赞 undefined 5/4/2020
Javascript 是一种松散类型的语言:)。所以在我看来,如果是这样的话,那么我会选择打字稿流程之类的东西。XD的
0赞 mycroes 10/13/2020
当数组包含对象时,这也不能可靠地工作,因为 OTOH 也不会执行浅层比较。JSON.stringify
12赞 Kamil Kiełczewski 11/8/2019 #40

最短

对于数字数组,请尝试:

a1==''+a2

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

console.log( a1==''+a2 )

注意:当数组还包含字符串时,此方法将不起作用,例如 .a2 = [1, "2,3"]

3赞 jpthesolver2 12/30/2019 #41

使用过滤器和箭头函数的另一种方法

arrOne.length === arrTwo.length && arrOne.filter((currVal, idx) => currVal !== arrTwo[idx]).length === 0
-1赞 user11748403 1/18/2020 #42
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
4赞 Jöcker 8/14/2020 #43

这里是未排序数组和自定义比较的可能性:

    const array1 = [1,3,2,4,5];
    const array2 = [1,3,2,4,5];
    
    const isInArray1 = array1.every(item => array2.find(item2 => item===item2))
    const isInArray2 = array2.every(item => array1.find(item2 => item===item2))
    
    const isSameArray = array1.length === array2.length && isInArray1 && isInArray2
    
    console.log(isSameArray); //true
7赞 CertainPerformance 8/26/2020 #44

2020 年推出了一个 Stage 1 提案,允许通过添加到语言中来轻松比较数组。这是它的工作方式,没有任何库、猴子补丁或任何其他代码:Array.prototype.equals

[1, 2, 3].equals([1, 2, 3]) // evaluates to true
[1, 2, undefined].equals([1, 2, 3]) // evaluates to false
[1, [2, [3, 4]]].equals([1, [2, [3, 4]]]) // evaluates to true

到目前为止,这只是一个暂定提案——TC39 现在将“花时间研究问题空间、解决方案和跨领域关注点”。如果它进入第 2 阶段,它很有可能最终被集成到语言中。

11赞 Hamza Hmem 9/27/2020 #45

您可以简单地使用 lodash 库中的 isEqual。它非常高效和干净。

import isEqual from "lodash/isEqual";

const isTwoArraysEqual = isEqual(array1, array2);

评论

2赞 Ali Celebi 6/11/2021
使用 lodash 比较数组既简单又好。
0赞 Hamza Hmem 6/12/2021
@HadidAli 是的,在编程中,你不应该构建已经由其他开发人员或团队构建的东西,或者存在于像 Lodash 这样的轻量级库中
0赞 marcofriso 3/8/2022
使用 Lodash isEqual 和 sortBy:isEqual(sortBy(array1), sortBy(array2));
0赞 shreyasm-dev 9/29/2020 #46

这种方法只适用于标量数组,就像这个问题的第二个投票答案一样。

var arrs = [
  [[1, 2, 3], [1, 2, 3]], // true
  [[1, 2, 3, 4], [1, 2, 3]], // false
  [[1, 2, 3], [1, 2, 3, 4]], // false
]

const arraysEqual = (one, two) => (one.filter((i, n) => two[n] === i).length === one.length) && (two.filter((i, n) => one[n] === i).length === two.length)

arrs.forEach(arr => {
  console.log(arraysEqual(arr[0], arr[1]))
})

没有 ES6 语法:

var arrs = [
  [[1, 2, 3], [1, 2, 3]], // true
  [[1, 2, 3, 4], [1, 2, 3]], // false
  [[1, 2, 3], [1, 2, 3, 4]], // false
]

function arraysEqual(one, two) {
  return (one.filter((i, n) => two[n] === i).length === one.length) && (two.filter((i, n) => one[n] === i).length === two.length)
}

arrs.forEach(arr => {
  console.log(arraysEqual(arr[0], arr[1]))
})

3赞 movAhed 1/14/2021 #47

这是一个棘手的隐式数组相等性检查,但可以在将数组连贯到字符串之后立即处理该工作。

var a1 = [1, 2, 3];
var a2 = [1, 2, 3];
var isEqual = a1 <= a2 && a1 >= a2; // true
0赞 ninjagecko 5/3/2021 #48

我在 https://stackoverflow.com/a/10316616/711085 上回答了这个问题(此后被标记为此答案的重复)。在那里,您将找到一个 Deep Equals 实现,它可以处理许多情况,例如 MapSet 以及数组和对象的任意嵌套。其中对 == 的非传递性和记录 == vs === 的讨论尤为重要。


对于 OP 的特殊问题,如果数组仅由数字、字符串和布尔值组成,而没有 NaN,那么对于足够大的数组,最有效的方法是预编译函数:

function areSimpleArraysEqual(a,b) {
    // requires inputs be arrays of only Number, String, Boolean, and no NaN.
    // will propagate error if either array is undefined.
    if (a.length!=b.length)
        return false;
    for(let i=0; i<a.length; i++)
        if (a[i]!==b[i]) // using === equality
            return false;
    return true;
}

在极少数情况下,如果一个人的业务逻辑不断追加到数组的末尾,则可以通过检查 .if (a.length>0 && a[a.length-1]!==b[b.length-1]) return false;

评论

1赞 julie 4/25/2022
我感到难以置信的是,如此广泛使用的语言却缺少如此重要的操作。Python 和其他一些语言更理智(如果 a 和 b 是具有相同元素的数组,则 a==b 为 true)。身份是一个不同的问题(Python 中的 a 是 b)。顺便说一句,这个线程将列表和集合混为一谈。如果集合具有相同的元素,则它们是相等的,但对于列表/数组,元素必须具有相同的顺序才能相等。
4赞 Filip Seman 5/25/2021 #49

简单

type Values = number | string;

/** Not sorted array */
function compare<Values>(a1: Array<Values>, a2: Array<Values>): boolean {
    if (a1.length !== a2.length) {
        return false;
    }

    /** Unique values */
    const set1 = new Set<Values>(a1);
    const set2 = new Set<Values>(a2);
    if (set1.size !== set2.size) {
        return false;
    }

    return [...set1].every((value) => [...set2].includes(value));
}

compare([1, 2, 3], [1, 2, 3]);    // true
compare([1, 2, 3], [1, 3, 2]);    // true
compare([1, 1, 1], [1, 2, 3]);    // false
compare([1, 1, 2, 3], [1, 2, 3]); // false

/** Sorted arrays, faster method */
function compareSorted<Values>(a1: Array<Values>, a2: Array<Values>): boolean {
    if (a1.length !== a2.length) {
        return false;
    }

    /** Unique values */
    const set1 = new Set<Values>(a1);
    const set2 = new Set<Values>(a2);
    if (set1.size !== set2.size) {
        return false;
    }

    return [...set1].every((value, index) => value === [...set2][index]);
}

compareSorted([1, 2, 3], [1, 2, 3]);    // true
compareSorted([1, 2, 3], [1, 3, 2]);    // false
compareSorted([1, 1, 1], [1, 2, 3]);    // false
compareSorted([1, 1, 2, 3], [1, 2, 3]); // false
8赞 swift-lynx 5/29/2021 #50

代码高尔夫

有很多答案显示了如何有效地比较数组。

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

const a = [1, 2, 3]
const 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)

// even shorter
console.log("4. b) ", a == "" + b)

// false positives (see flaws)
console.log("5. ", 1 + ["3"] == 1 + [3]) // type differences
console.log("6. ", 1 + ["1,2"] == 1 + ["1", "2"])

解释

这之所以有效,是因为在使用运算符时,类型会自动转换以允许串联。在本例中,和 the 都转换为字符串。+1[1, 2, 3]

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

缺陷

使用这种技术,比较并不关心要比较的数组中的元素是否属于不同类型。 将等于,因为字符串转换。[1, 2]["1", "2"]

编辑:正如评论中指出的,比较字符串数组可能会产生误报,例如“等于”.如果您确定这些永远不会发生(例如,在许多代码高尔夫挑战中),则无需担心。["1,2"]["1", "2"]

免責聲明

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

评论

0赞 sparkyspider 7/13/2021
啊。单纯。
1赞 Kamil Kiełczewski 8/6/2021
它适用于数字,但不适用于字符串数组,例如 和(因此您可以指出您的答案仅适用于数字)1+["1","2,3"]===1+["1,2","3"]["1","2,3"].join()===["1,2","3"].join()
0赞 swift-lynx 8/6/2021
我什至没有想到......如果这种边缘情况令人担忧,我的解决方案将不起作用。我更新了我的答案,清楚地说明了这个缺陷。
1赞 Collin Thomas 6/27/2021 #51

所有其他解决方案看起来都很复杂。这可能不是最有效的,或者处理所有边缘情况,但它对我来说效果很好。

Array.prototype.includesArray = function(arr) {
  return this.map(i => JSON.stringify(i)).includes(JSON.stringify(arr))
}

用法

[[1,1]].includesArray([1,1])
// true

[[1,1]].includesArray([1,1,2])
// false

评论

0赞 Domino 6/15/2022
这是非常无效的,如果这些数组中的任何一个包含递归结构或其他不可序列化的东西,则会产生 arror。
2赞 Mihailoff 11/4/2021 #52

令人惊讶的是,没有人提出带有 find 的解决方案

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
}

评论

3赞 VLAZ 11/4/2021
a.find((v,i) => v !== b[i])与直接返回布尔值的差值完全等价。 并且也通过否定而相互等价:。当我运行基准测试时,代码排在变体前面的第二位。a.some((v,i) => v !== b[i]).some().some().every()a.every((v,i) => v -== b[i]).every().find()
9赞 Aditya 11/23/2021 #53

给你

const a = [1, 2, 3]
const b = [1, 2, 3, 4, 5]

const diff = b.filter(e => !a.includes(e))
console.log(diff)

上面的大多数答案都不适用于无序列表。 这也适用于无序列表。

const a = [3, 2, 1]
const b = [1, 2, 3, 4, 5]

const diff = b.filter(e => !a.includes(e))
console.log(diff)

如果 a 的大小大于 b,

const a = [1, 2, 3, 4, 5]
const b = [3, 2, 1]

const diff = a.length > b.length ? a.filter(e => !b.includes(e)) : b.filter(e => !a.includes(e))
console.log(diff)

评论

0赞 Aditya 5/11/2022
上面的解决方案试图在 a [1,2,3] 中找到 b [3,2,3] 中不存在的数字,就您的情况而言,b (2,3) 中的所有唯一数字都存在于 a (1,2,3) 中,这就是它打印空数组的原因。
1赞 Aditya 6/18/2022
@AkshayVijayJain,你可以比较数组的长度,const diff = a.length > b.length ?a.filter(e => !b.includes(e)) : b.filter(e => !a.includes(e))
9赞 michaels234 12/14/2021 #54

这里有很多复杂的长答案,所以我只想贡献一个非常简单的答案:使用 toString() 将数组转换为一个简单的逗号分隔字符串,您可以轻松地将其与 === 进行比较

let a = [1, 2, 3]
let b = [1, 2, 3]
let c = [4, 2, 3]

console.log(a.toString())  // this outputs "1,2,3"
console.log(a.toString() === b.toString())  // this outputs true because "1,2,3" === "1,2,3"
console.log(a.toString() === c.toString())  // this outputs false because "1,2,3" != "4,2,3"

评论

0赞 Spleen 4/16/2022
如果第二个数组具有相同的值但索引不同,这不是一个好方法。 !== .所以也许你需要先对数组进行排序。1,2,33,2,1
0赞 Akshay Vijay Jain 6/15/2022
我想知道有人怎么会投票给这个答案,当元素的顺序不同时,它将不起作用
2赞 michaels234 6/16/2022
因为通常元素的顺序很重要,而 2 个具有不同元素顺序的不同数组是不一样的。您不能以相同的方式使用它们或使用相同的索引等访问它们。
8赞 Ankit Kumar 3/28/2022 #55

这里有很多好的答案。这就是我通常的做法——

if ( arr1.length === arr2.length && arr1.every((a1) => arr2.includes(a1)) ) {
   // logic
}

every()仅当所有元素都通过给定的 camparison 时才会返回 true 逻辑。如果它遇到 false,在任何迭代中,它都会终止并 返回 false。

时间复杂度为 O(n*m)。

0赞 Julien Duris 7/25/2023 #56

如果你喜欢简单的野蛮:

const a1 = ['a', 'b', 'e', 'd', 'c'];
const a2 = ['a', 'b', 'c', 'd', 'e'];

a1.length === a2.length && [...a1, ...a2].filter((item) => a2.indexOf(item) === -1).length === 0

请注意,您可以在 2 个数组中的任何一个上执行“indexOf”。

评论

0赞 Julien Duris 8/9/2023
我想我得到了反对票,因为这个解决方案没有断言密钥以相同的方式排序。OP 没有准确说明它,我想我可以从“相同”一词中推导出来。尽管如此,这个解决方案被证明非常有用,对于一系列“原语”,并且与其他解决方案相比非常有效。
0赞 Heretic Monkey 11/9/2023
也可能是在 2016 年推出时失宠。indexOf(item) === -1! includes(item)