【问题标题】:How to compare arrays in JavaScript?如何比较 JavaScript 中的数组?
【发布时间】:2022-01-21 07:44:28
【问题描述】:

我想比较两个数组......理想情况下,高效。没什么特别的,只要true 相同,false 否则。毫不奇怪,比较运算符似乎不起作用。

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

【问题讨论】:

  • 您可以先比较它们的长度,以及它们是否相等。
  • 是什么让两个数组对你来说相等?相同的元素?相同的元素顺序?仅当数组的元素可以序列化为 JSON 时,编码为 JSON 才有效。如果数组可以包含对象,你会去多深?什么时候两个对象“相等”?
  • @FelixKling,定义“平等”绝对是一个微妙的话题,但对于从高级语言开始接触 JavaScript 的人来说,没有像 ([] == []) == false 这样愚蠢的借口。
  • @AlexD 看起来数组使用引用相等,这是您所期望的。如果你不能这样做,那就太糟糕了
  • @AlexD 我有点想不出一种不会发生这种情况的语言。在 C++ 中,您将比较两个指针 - 错误。在 Java 中,您所做的与在 javascript 中相同。在 PHP 中,幕后的东西会在数组中循环——你称 PHP 为高级语言吗?

标签: javascript arrays json


【解决方案1】:

这里有很多复杂的长答案,所以我只想提供一个非常简单的答案:使用 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"

【讨论】:

    【解决方案2】:

    给你,

    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)

    【讨论】:

      【解决方案3】:

      令人惊讶的是,没有人提出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
      }
      

      【讨论】:

      • 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() 变体之前的第二位。
      【解决方案4】:

      代码打高尔夫球

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

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

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

      说明

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

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

      缺陷

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

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

      免责声明

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

      【讨论】:

      • 啊啊啊。简单。
      • 它适用于数字,但不适用于字符串数组,例如1+["1","2,3"]===1+["1,2","3"]["1","2,3"].join()===["1,2","3"].join()(因此您可以表明您的答案仅适用于数字)
      • 我什至没有考虑过......如果担心这种边缘情况,我的解决方案将无法工作。我更新了我的答案以明确说明这个缺陷。
      【解决方案5】:

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

      比较数组:

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

      这是有原因的,因为可能有,例如private variables within objects.

      但是,如果你只是使用对象结构来包含数据,还是可以进行比较的:

      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 之类的数据,而不是类实例和其他内容。如果您想比较更复杂的对象,请查看this answer and it's super long function
      要使其与 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]) {
      ...
      

      我发了little test tool for both of the functions

      奖励:indexOfcontains 的嵌套数组

      Samy Bencherif has prepared 用于在嵌套数组中搜索特定对象的有用函数,可在此处获得:https://jsfiddle.net/SamyBencherif/8352y6yw/

      【讨论】:

      • 如果您想进行严格的比较,请使用this[i] !== array[i] 而不是!=
      • 你的方法应该被称为equals而不是compare。至少在 .NET 中,比较通常返回一个带符号的 int,指示哪个对象大于另一个。请参阅:Comparer.Compare
      • 这不仅是正确的做法,而且效率也相当高。这是我为这个问题中建议的所有方法准备的快速 jsperf 脚本。 jsperf.com/comparing-arrays2
      • 更改内置类型的原型绝对不是正确的方法
      • 此外,这不是关于它是否易于重写,而是关于答案不应该推荐被认为是不好的做法 (developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/…) 并且应该绝对不要在标题“正确的方式”下方这样做
      【解决方案6】:

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

      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
      

      【讨论】:

        【解决方案7】:

        我相信简单的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;
            }
            
        }
        

        【讨论】:

        • 为什么需要反之亦然检查?我们知道数组的大小相同,所以如果 array1 中的每个项目也在 array2 中找到;为什么我们还要检查 array2 中的每个项目是否也在 array1 中?
        • 第一个数组可能是 [1,1] 第二个 [1,2],反之亦然,这是无法检测到的
        【解决方案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;
        }
        

        【讨论】:

          【解决方案9】:

          简单

          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
          

          【讨论】:

            【解决方案10】:

            有了functional Programming approach我们可以用下面的代码来实现。

            const a1 = [1, 2, 22, 4];
            const a2 = [4, 2, 22, 1];
            
            const checkValue = (firstValues: number[]) => {
              return (value: number) => {
                const isEqual = firstValues.includes(value);
                return isEqual
              }
            }
            
            const notUniq = a1.map(checkValue(a2)).some((x) => !x) // false
            

            【讨论】:

              【解决方案11】:

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


              对于 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&gt;0 &amp;&amp; a[a.length-1]!==b[b.length-1]) return false;,在极少数情况下,如果一个人的业务逻辑一直附加到数组的末尾,则可以实现平均情况 O(1) 和最坏情况 O(N)。

              【讨论】:

                【解决方案12】:

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

                var a1 = [1, 2, 3];
                var a2 = [1, 2, 3];
                var isEqual = a1 <= a2 && a1 >= a2; // true
                

                【讨论】:

                  【解决方案13】:

                  最短

                  对于数字数组试试:

                  a1==''+a2
                  

                  var a1 = [1,2,3];
                  var a2 = [1,2,3];
                  
                  console.log( a1==''+a2 )

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

                  【讨论】:

                    【解决方案14】:

                    如果你正在编写测试代码,那么

                    import chai from 'chai';
                    const arr1 = [2, 1];
                    const arr2 = [2, 1];
                    chai.expect(arr1).to.eql(arr2); // Will pass. `eql` is data compare instead of object compare.
                    

                    【讨论】:

                      【解决方案15】:

                      我认为最简单的方法是像你尝试的那样将每个数组变成一个字符串,然后比较字符串。

                      要将数组转换为字符串,只需将此字符串方法放入数组即可。 这些是数组:

                      var arr1 = [1, 2, "foo", 3, "bar", 3.14]
                      var arr2 = [1, 2, "foo", 3, "bar", 3.14]
                      

                      现在,您必须将它们转换为字符串。方法列表是:

                      arr1.toString().replace(/,/gi, "")
                      arr2.toString().replace(/,/gi, "")
                      

                      方法做:

                      **.toString()**-

                      将数组转换为字符串,连接数组的元素。

                      例如。 ["tree", "black hole"] -> "tree,black hole"

                      遗憾的是,它包含逗号。这就是为什么我们必须这样做:

                      ***.replace(a, b)***
                      

                      它会在你正在处理的字符串中找到第一个参数 (a) 并将其替换为第二个参数 (b)。

                      例如

                      "0000010000010000000".replace("1", "2")
                      

                      将返回:"0000020000010000000"

                      它只替换了参数1的第一个实例,所以我们可以用正则表达式代替。

                      例如

                      "0000010000010000000".replace(/1/gi, "2")
                      

                      将返回:"0000020000020000000"

                      你用 / 包裹你想要替换的东西。 说你要替换的是 1。你做到了:/1/。 但是你必须在最后添加 gi 以便它选择每个实例。 所以,你必须把 /1/gi 用逗号放在最后,然后你可以把你想用的替换它。

                      现在,您的两个数组是:

                      arr1:"12foo3bar3.14" arr2:"12foo3bar3.14"

                      现在你这样说:

                      if(arr1 === arr2) {
                        // Now the code you put inside of this if statement will only run if arr1 and arr2 have the same contents.
                      } else {
                        // This code will run if arr1 and arr2 have any differences.
                      }
                      

                      如果您想检查 arr1 是否包含 arr2 而不是具有相同的确切内容,请执行此操作。

                      if(arr1.indexOf(arr2) !== -1) {
                          //This code will happen if arr2 is inside of arr1. If there is one extra array 
                          //item in arr1, it doesn't matter. But, if arr2 has an extra array item, nothing in 
                          //this if will run. If you want arr2 to contain arr1, just make arr1 in the 
                          //condition of this if arr2, and make arr2 arr1.
                      }
                      

                      基本上,如果您希望数组完全相同,请执行以下操作:

                      if(arr1.toString().replace(/,/gi, "") === arr2.toString().replace(/,/gi, "")) {
                          //arrays are the same
                      } else {
                          //arrays are different
                      }
                      

                      如果您想知道一个数组是否包含另一个数组,只需这样做:

                      arrayThatWillHoldAnotherArray = arrayThatWillHoldAnotherArray.toString().replace(/,/gi)
                      arrayThatWillBeInsideAnotherArray = arrayThatWillBeInsideAnotherArray.toString().replace(/,/gi)
                      
                      
                      if(arrayThatWillHoldAnotherArray.indexOf(arrayThatWillBeInsideAnotherArray) !== -1) {
                          //arrayThatWillHoldAnotherArray has arrayThatWillBeInsideAnotherArray inside of it
                      } else {
                          //it doesn't
                      }
                      

                      console.log("Read the code to understand this.")
                      var arr1 = [1,2,"foo",3,"bar",3.14]
                      var arr2 = [1,2,"foo",3,"bar",3.14]
                      function checkIfArraysAreTheSame(a,b) {
                        if(a.toString().replace(/,/gi,"") === b.toString().replace(/,/gi,"")) {
                          console.log("A and B are the same!")
                          return true;
                        }
                        console.log("A and B are NOT the same!")
                        return false
                      }
                      checkIfArraysAreTheSame(arr1,arr2)
                      //expected output: A and B are the same!
                      //Now, let's add another item to arr2.
                      arr2.push("Lorem")
                      checkIfArraysAreTheSame(arr1,arr2)
                      //expected output: A and B are NOT the same!
                      
                      function checkIfArrayIsNestedInsideAnother(a,b) {
                        //If this returns true, b is nested inside a.
                        if (a.toString().replace(/,/gi,"").indexOf(b.toString().replace(/,/gi,"")) > -1) {
                          console.log("B is nested inside of A!")
                        } else if(b.toString().replace(/,/gi,"").indexOf(a.toString().replace(/,/gi,"")) > -1) {
                          console.log("A is nested inside of B!")
                        }
                      }
                      
                      checkIfArrayIsNestedInsideAnother(arr1, arr2)
                      //expected output: A is nested inside of B! because:
                      //arr1 (a): [1,2,"foo",3,"bar",3.14]
                      //arr2 (b): [1,2,"foo",3,"bar",3.14, "Lorem"]
                      //We added Lorem at line 15.
                      
                      //Now, let's check if arr2 is nested inside arr1, which it is not.
                      checkIfArrayIsNestedInsideAnother(arr2, arr1)
                      //expected output: B is nested inside of A!

                      【讨论】:

                      • 首先,这个在大阵列上会很慢,因为替换的工作方式arr1.toString().replace(/,/gi, ""),所以你可以使用arr1.join(''),它会做到这一点。不幸的是,对于任何嵌套对象,这将作为检查失败。即使["1"][1] 也会被视为平等,这是错误的
                      【解决方案16】:

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

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

                      【讨论】:

                        【解决方案17】:

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

                        import {isEqual} from "lodash";
                        
                        const isTwoArraysEqual = isEqual(array1, array2);
                        

                        【讨论】:

                        • 使用 lodash 比较数组非常简单。
                        • @HadidAli 是的,在编程中你不应该构建已经由其他开发人员或团队构建的东西,或者存在于像 Lodash 这样的轻量级库中
                        【解决方案18】:

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

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

                        Rr,在 ECMAScript 6 / CoffeeScript / 带有箭头函数的 TypeScript 中:

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

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

                        更新

                        根据我从 cmets 读取的内容,对数组进行排序和比较可能会给出准确的结果:

                        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

                        【讨论】:

                        • 我喜欢这个,尽管读者应该知道这仅适用于排序数组。
                        • 它适用于任何类型的数组,无论是否排序@espertus
                        • 是的,完全正确。这个函数应该是比较两个数组,不管它们是否排序,它们的连续元素必须相等。
                        • @espertus 实际上,如果元素在两个数组中的顺序不同,它就不会返回 true。但是,相等性检查的目标不是检查它们是否包含相同的元素,而是检查它们是否具有相同顺序的相同元素。
                        • 如果要检查两个数组是否相等,包含相同的未排序项(但未多次使用),您可以使用a1.length==a2.length &amp;&amp; a1.every((v,i)=&gt;a2.includes(v))var a1 =[1,2,3], a2 = [3,2,1];var a1 =[1,3,3], a2 = [1,1,3]; 不会作为预计)
                        【解决方案19】:

                        这里可以进行未排序的数组和自定义比较:

                            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
                        

                        【讨论】:

                          【解决方案20】:

                          Stage 1 proposal 于 2020 年推出,可通过在语言中添加 Array.prototype.equals 来轻松比较数组。这就是它的工作方式,无需任何库、monkeypatching 或任何其他代码:

                          [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 will now“花时间研究问题空间、解决方案和跨领域关注点”。如果它进入第 2 阶段,它很有可能最终被整合到适当的语言中。

                          【讨论】:

                            【解决方案21】:

                            在 'forEach' 中使用 'includes' 怎么样?

                                var array1 = [1,2,3];
                                var array2 = [1,2,4];
                                var array_diff = 0;
                                // loop through each element in first array
                                array1.forEach(function(elem){
                                    // check if second array contains it, return false if not
                                    if(!array2.includes(elem)){
                                        array_diff = 1;
                                        return false;
                                    }else{
                                        array_diff = 0;
                                    }
                                });
                                // loop through each element in second array
                                array2.forEach(function(elem){
                                    // check if first array contains it, return false if not
                                    if(!array1.includes(elem)){
                                        array_diff = 1;
                                        return false;
                                    }else{
                                        array_diff = 0;
                                    }
                                });
                                // variable array_diff determines the result
                                if(array_diff == 1){
                                    alert('Arrays are different');
                                }else{
                                    alert('Arrays are same');
                                }
                            

                            注意:这应该适用于已排序和未排序的数组

                            【讨论】:

                            • 1.在 [1,2,3]、[1,1,2,3](重复元素)上失败。 2. 即使它确实有效,includes 也必须一次扫描一个元素,因此当您知道两个索引处的项目必须匹配时,对两个数组中的每个元素都这样做是非常低效的。
                            【解决方案22】:

                            我知道 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。

                            =)

                            【讨论】:

                            • 请注意,这种比较也适用于与字符串相比的数组。
                            • @EliasDorneles,非常感谢!在将变量分配给模板字符串文字之前,我更新了我的答案以执行检查。
                            • 呵呵,现在它会说这两个是相等的a = ["1,1", "2"]b = [1,1,2](或b = ["1", "1,2"])......我认为用这种方法很难得到强大的东西。 ^^
                            • Javascript 是一种松散类型的语言 :)。所以在我看来,如果是这样的话,我会选择typescriptflow 之类的东西。 XD
                            • 当数组包含对象时,这也不能可靠地工作,其中 OTOH JSON.stringify 也不会执行浅比较。
                            【解决方案23】:

                            我需要类似的东西,比较两个包含标识符但以随机顺序排列的数组。 在我的情况下:“这个数组是否至少包含另一个列表中的一个标识符?” 代码很简单,使用reduce函数。

                            function hasFullOverlap(listA, listB){ 
                               return listA.reduce((allIdsAreFound, _id) => {
                                     // We return true until an ID has not been found in the other list
                                      return listB.includes(_id) && allIdsAreFound;
                                    }, true);
                            }
                            
                            if(hasFullOverlap(listA, listB) && hasFullOverlap(listB, listA)){
                               // Both lists contain all the values
                            }
                            

                            【讨论】:

                              【解决方案24】:

                              这个简单的解决方案适合我

                              function areEqual(a, b){
                                  let x = 0;
                                  for (n in a){
                                      if (a[n] == b[n]){x = 1;}
                                      else {x = 0};
                                  }
                                  return x;
                              }
                              
                              a = [1,2,3];
                              b = [1,2,3];
                              

                              > console.log(areEqual(a,b))

                              是的

                              我在这个简单的真实代码应用中使用了它

                              <script>
                              let corrette = [1];
                              let risposte = [];
                              
                              function areEqual(a, b){
                              	let x = 0;
                              	for (n in a){
                              		if (a[n] == b[n]){x = 1;}
                              		else {x = 0};
                              	}
                              	if (x){console.log("The 2 arrays are equal")}
                              	return x;
                              }
                              
                              </script>
                              
                              Apporto di attrezzatura per cucina da parte del proprietario
                              <button onclick="risposte[0]=1">Capitale proprio</button>
                              <button onclick="risposte[0]=0">Capitale di debito</button>
                              <button onclick="risposte[0]=0">Debito commerciale</button>
                              
                              <br><hr>
                              <button onclick="if(areEqual(corrette,risposte)){controlla.innerHTML='Esatto'}else{controlla.innerHTML='No'}">Controlla le risposte</button>
                              <div id="controlla"></div>

                              【讨论】:

                              • 这是一个糟糕的解决方案。它不处理它应该处理的基本内容:areEqual( [1,2,3], [1,2,3,4] )areEqual([1,4,3], [1,2,3]) 将产生它不应该产生的“1”。而且它实际上根本没有优化。没有必要在每次“好的”和最坏的情况下都保持“1”:如果它不是“好的”,则无需继续。就在那个时候回来。您还应该使用真正的 bool 'true' 或 'false'。使用数字只会使这更加混乱。最低限度是在函数的开头添加一个检查来验证两个数组是否相等,如果不是则不需要继续
                              • 请修复或考虑删除此答案,因为它是完全错误的。
                              【解决方案25】:

                              如果您想比较两个数组并检查两个数组中是否有相同的对象,它将起作用。示例:

                              Array1 = [a,b,c,d] Array2 = [d,e,f,g]

                              这里,'d'在两个数组中都是通用的,所以这个函数将返回真值。

                               cehckArray(array1, array2) {
                                  for (let i = 0; i < array1.length; i++) {
                                    for (let j = 0; j < array2.length; j++) {
                                      if (array1[i] === array2[j]) {
                                        return true;
                                      }
                                    }
                                  }
                                  // Return if no common element exist 
                                  return false;
                                }
                              

                              【讨论】:

                              • 这不能回答问题。此函数测试两个数组是否有共同的交集(当解释为集合时)。
                              【解决方案26】:
                              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
                              

                              【讨论】:

                                【解决方案27】:

                                我们可以使用every()和includes()方法来比较两个数组。

                                function check(a1,a2){
                                
                                  let result = a1.every((x)=>{
                                  return a2.includes(x);
                                 });
                                
                                return result; 
                                } 
                                

                                【讨论】:

                                • 给定参数的结果将为真const a1 = [1, 2, 3]; const a2 = [1, 2, 3, 4];您应该检查数组长度是否匹配。
                                【解决方案28】:

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

                                arrOne.length === arrTwo.length && arrOne.filter((currVal, idx) => currVal !== arrTwo[idx]).length === 0
                                

                                【讨论】:

                                  【解决方案29】:
                                  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  
                                  

                                  【讨论】:

                                    【解决方案30】:

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

                                    看看我的代码和你的例子,它比较了两个元素是数字的数组,你可以修改或扩展它以用于其他元素类型(通过使用 .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);

                                    【讨论】:

                                      猜你喜欢
                                      相关资源
                                      最近更新 更多