如何比较 JavaScript 中的数组?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7837456/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 03:47:31  来源:igfitidea点击:

How to compare arrays in JavaScript?

javascriptarraysjson

提问by Julian H. Lam

I'd like to compare two arrays... ideally, efficiently. Nothing fancy, just trueif they are identical, and falseif not. Not surprisingly, the comparison operator doesn't seem to work.

我想比较两个数组......理想情况下,有效地。没什么特别的,只要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 encoding each array does, but is there a faster or "better" way to simply compare arrays without having to iterate through each value?

JSON 编码每个数组都可以,但是有没有更快或“更好”的方法来简单地比较数组而不必遍历每个值?

采纳答案by Tomá? Zato - Reinstate Monica

To compare arrays, loop through them and compare every value:

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

Comparing arrays:

比较数组:

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

Usage:

用法:

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

You may say "But it is much faster to compare strings - no loops..." well, then you should note there ARE loops. First recursive loop that converts Array to string and second, that compares two strings. So this method is faster than use of string.

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

I believe that larger amounts of data should be always stored in arrays, not in objects. However if you use objects, they can be partially compared too.
Here's how:

我相信更大量的数据应该始终存储在数组中,而不是存储在对象中。但是,如果您使用对象,它们也可以进行部分比较。
就是这样:

Comparing objects:

比较对象:

I've stated above, that two object instanceswill never be equal, even if they contain same data at the moment:

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

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

This has a reason, since there may be, for example private variables within objects.

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

However, if you just use object structure to contain data, comparing is still possible:

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

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

However, remember that this one is to serve in comparing JSON like data, not class instances and other stuff. If you want to compare mor complicated objects, look at this answer and it's superlong function.
To make this work with Array.equalsyou must edit the original function a little bit:

但是,请记住,这是用于比较 JSON 之类的数据,而不是类实例和其他东西。如果你想比较更复杂的对象,看看这个答案,它是 superlong 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]) {
...

I made a little test tool for both of the functions.

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

Bonus: Nested arrays with indexOfand contains

奖励:带有indexOf和的嵌套数组contains

Samy Bencherif has prepareduseful functions for the case you're searching for a specific object in nested arrays, which are available here: https://jsfiddle.net/SamyBencherif/8352y6yw/

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

回答by user2782196

While this only works for scalar arrays (see note below), it is short:

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

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

Rr, in ECMAScript 6 / CoffeeScript / TypeScript with Arrow Functions:

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

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

(Note: 'scalar' here means values that can be compared directly using ===. So: numbers, strings, objects by reference, functions by reference. See the MDN referencefor more info about the comparison operators).

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

UPDATE

更新

From what I read from the comments, sorting the array and comparing may give accurate result:

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

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

Eg:

例如:

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

Then the above code would give true

然后上面的代码会给 true

回答by Jason Boerner

I like to use the Underscore library for array/object heavy coding projects ... in Underscore and Lodash whether you're comparing arrays or objects it just looks like this:

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

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

回答by radtek

This I think is the simplest way to do it using JSON stringify, and it may be the best solution in some situations:

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

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

This converts the objects a1and a2into strings so they can be compared. The order is important in most cases, for that can sort the object using a sort algorithm shown in one of the above answers.

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

Please do note that you are no longer comparing the object but the string representation of the object. It may not be exactly what you want.

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

回答by Tim Down

It's unclear what you mean by "identical". For example, are the arrays aand bbelow identical (note the nested arrays)?

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

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

Here's an optimized array comparison function that compares corresponding elements of each array in turn using strict equality and does not do recursive comparison of array elements that are themselves arrays, meaning that for the above example, arraysIdentical(a, b)would return false. It works in the general case, which JSON- and join()-based solutions will not:

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

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

回答by Thank you

The Practical Way

实用的方法

I think it's wrong to say a particular implementation is "The Right Way?" if it's only "right" ("correct") in contrast to a "wrong" solution. Tomá?'s solution is a clear improvement over string-based array comparison, but that doesn't mean it's objectively "right". What is rightanyway? Is it the fastest? Is it the most flexible? Is it the easiest to comprehend? Is it the quickest to debug? Does it use the least operations? Does it have any side effects? No one solution can have the best of all the things.

我认为说一个特定的实现是“正确的方式?”是错误的。如果与“错误”解决方案相比,它只是“正确”(“正确”)。Tomá? 的解决方案是对基于字符串的数组比较的明显改进,但这并不意味着它客观上是“正确的”。什么是的?它是最快的吗?它是最灵活的吗?是不是最容易理解?是不是调试最快?它使用最少的操作吗?它有任何副作用吗?没有一种解决方案可以发挥所有事情的最佳效果。

Tomá?'s could say his solution is fast but I would also say it is needlessly complicated. It tries to be an all-in-one solution that works for all arrays, nested or not. In fact, it even accepts more than just arrays as an input and still attempts to give a "valid" answer.

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



Generics offer reusability

泛型提供可重用性

My answer will approach the problem differently. I'll start with a generic arrayCompareprocedure that is only concerned with stepping through the arrays. From there, we'll build our other basic comparison functions like arrayEqualand arrayDeepEqual, etc

我的回答会以不同的方式解决这个问题。我将从一个arrayCompare只与遍历数组有关的通用过程开始。从那里,我们将构建其他基本的比较函数,如arrayEqualandarrayDeepEqual

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

In my opinion, the best kind of code doesn't even need comments, and this is no exception. There's so little happening here that you can understand the behaviour of this procedure with almost no effort at all. Sure, some of the ES6 syntax might seem foreign to you now, but that's only because ES6 is relatively new.

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

As the type suggests, arrayComparetakes comparison function, f, and two input arrays, xsand ys. For the most part, all we do is call f (x) (y)for each element in the input arrays. We return an early falseif the user-defined freturns false– thanks to &&'s short-circuit evaluation. So yes, this means the comparator can stop iteration early and prevent looping through the rest of the input array when unnecessary.

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



Strict comparison

严格比较

Next, using our arrayComparefunction, we can easily create other functions we might need. We'll start with the elementary arrayEqual

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

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

Simple as that. arrayEqualcan be defined with arrayCompareand a comparator function that compares ato busing ===(for strict equality).

就那么简单。arrayEqual可以用arrayCompare和 一个比较器函数来定义,该函数abusing进行比较===(严格相等)。

Notice that we also define equalas it's own function. This highlights the role of arrayCompareas a higher-order function to utilize our first order comparator in the context of another data type (Array).

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



Loose comparison

松散的比较

We could just as easily defined arrayLooseEqualusing a ==instead. Now when comparing 1(Number) to '1'(String), the result will be true

我们可以很容易地arrayLooseEqual使用 a==来定义。现在当比较1(Number) 和'1'(String) 时,结果将是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


Deep comparison (recursive)

深度比较(递归)

You've probably noticed that this is only shallow comparison tho. Surely Tomá?'s solution is "The Right Way?" because it does implicit deep comparison, right ?

您可能已经注意到,这只是肤浅的比较。Tomá 的解决方案肯定是“正确的方式?” 因为它确实进行了隐含的深度比较,对吧?

Well our arrayCompareprocedure is versatile enough to use in a way that makes a deep equality test a breeze …

好吧,我们的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

Simple as that. We build a deep comparator using anotherhigher-order function. This time we're wrapping arrayCompareusing a custom comparator that will check if aand bare arrays. If so, reapply arrayDeepCompareotherwise compare aand bto the user-specified comparator (f). This allows us to keep the deep comparison behavior separate from how we actually compare the individual elements. Ie, like the example above shows, we can deep compare using equal, looseEqual, or any other comparator we make.

就那么简单。我们使用另一个高阶函数构建了一个深度比较器。这次我们arrayCompare使用自定义比较器进行包装,该比较器将检查ab是否为数组。如果是,则重新应用arrayDeepComparecompare aandb到用户指定的比较器 ( f)。这使我们能够将深度比较行为与我们实际比较各个元素的方式分开。即,像上面的例子所示,我们可以深刻的比较使用equallooseEqual或其他任何比较,我们做。

Because arrayDeepCompareis curried, we can partially apply it like we did in the previous examples too

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

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

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

To me, this already a clear improvement over Tomá?'s solution because I can explicitlychoose a shallow or deep comparison for my arrays, as needed.

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



Object comparison (example)

对象比较(示例)

Now what if you have an array of objects or something ? Maybe you want to consider those arrays as "equal" if each object has the same idvalue …

现在如果你有一个对象数组或其他东西怎么办?如果每个对象都具有相同的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

Simple as that. Here I've used vanilla JS objects, but this type of comparator could work for anyobject type; even your custom objects. Tomá?'s solution would need to be completely reworked to support this kind of equality test

就那么简单。这里我使用了 vanilla JS 对象,但这种类型的比较器可以用于任何对象类型;甚至您的自定义对象。Tomá? 的解决方案需要完全重新设计以支持这种平等测试

Deep array with objects? Not a problem. We built highly versatile, generic functions, so they'll work in a wide variety of use cases.

带有对象的深数组?不是问题。我们构建了高度通用的通用函数,因此它们将适用于各种用例。

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


Arbitrary comparison (example)

任意比较(示例)

Or what if you wanted to do some other kind of kind of completely arbitrary comparison ? Maybe I want to know if each xis greater than each y

或者,如果您想做一些其他类型的完全任意比较怎么办?也许我想知道每个x是否都大于每个y……

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


Less is More

少即是多

You can see we're actually doing more with less code. There's nothing complicated about arrayCompareitself and each of the custom comparators we've made have a very simple implementation.

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

With ease, we can define exactly how we wish for two arrays to be compared — shallow, deep, strict, loose, some object property, or some arbitrary computation, or any combination of these — all using one procedure, arrayCompare. Maybe even dream up a RegExpcomparator ! I know how kids love those regexps …

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

Is it the fastest? Nope. But it probably doesn't need to be either. If speed is the only metric used to measure the quality of our code, a lot of really great code would get thrown away — That's why I'm calling this approach The Practical Way. Or maybe to be more fair, APractical Way. This description is suitable for this answer because I'm not saying this answer is only practical in comparison to some other answer; it is objectively true. We've attained a high degree of practicality with very little code that's very easy to reason about. No other code can say we haven't earned this description.

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

Does that make it the "right" solution for you ? That's up for youto decide. And no one else can do that for you; only you know what your needs are. In almost all cases, I value straightforward, practical, and versatile code over clever and fast kind. What you value might differ, so pick what works for you.

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



Edit

编辑

My old answer was more focused on decomposing arrayEqualinto tiny procedures. It's an interesting exercise, but not really the best (most practical) way to approach this problem. If you're interested, you can see this revision history.

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

回答by unitario

In the spirit of the original question:

本着原始问题的精神:

I'd like to compare two arrays... ideally, efficiently. Nothing fancy, just true if they are identical, and false if not.

我想比较两个数组...理想情况下,有效地没什么特别的,如果它们相同就为真,否则为假。

I have been running performance tests on some of the more simple suggestions proposed here with the following results(fast to slow):

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

while(67%)by Tim Down

(67%)by Tim Down

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

every(69%)by user2782196

每个(69%)由用户 2782196

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

reduce(74%)by DEIs

通过 DEI减少(74%)

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

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

加入& toString(78%)由 Gaizka Allende & vivek

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

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

half toString(90%)by Victor Palomo

half toString(90%)by Victor Palomo

a1 == a2.toString();

stringify(100%)by radtek

由 radtek字符串化(100%)

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

Notethe examples below assumes the arrays are sorted, single-dimensional arrays. .lengthcomparison has been removed for a common benchmark (add a1.length === a2.lengthto any of the suggestions and you will get a ~10% performance boost). Choose whatever solutions that works best for you knowing the speed and limitation of each.

Unrelated note:it is interesting to see people getting all trigger-happy John Waynes on the down vote button on perfectly legitimate answers to this question.

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

不相关的说明:有趣的是,看到人们对这个问题的完全合法的答案投了反对票,让所有触发快乐的约翰·韦恩斯(John Waynes)都投了反对票。

回答by Evan Steinkerchner

Building off Tomá? Zato's answer, I agree that just iterating through the arrays is the fastest. Additionally (like others have already stated), the function should be called equals/equal, not compare. In light of this, I modified the function to handle comparing arrays for similarity - i.e. they have the same elements, but out of order - for personal use, and thought I'd throw it on here for everyone to see.

建造Tomá?Zato 的回答,我同意只遍历数组是最快的。此外(就像其他人已经说过的那样),该函数应该被称为等于/等于,而不是比较。有鉴于此,我修改了函数来处理比较数组的相似性——即它们具有相同的元素,但乱序——供个人使用,并认为我会把它放在这里让大家看看。

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

This function takes an additional parameter of strict that defaults to true. This strict parameter defines if the arrays need to be wholly equal in both contents and the order of those contents, or simply just contain the same contents.

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

Example:

例子:

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

I've also written up a quick jsfiddle with the function and this example:
http://jsfiddle.net/Roundaround/DLkxX/

我还用函数和这个例子编写了一个快速的 jsfiddle:http:
//jsfiddle.net/Roundaround/DLkxX/

回答by Jeferson Euclides

Even though this has a lot of answers, one that I believe to be of help:

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

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

It is not stated in the question how the structure of the array is going to look like, so If you know for sure that you won't have nested arrays nor objectsin you array (it happened to me, that's why I came to this answer) the above code will work.

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

What happens is that we use spread operator ( ... ) to concat both arrays, then we use Set to eliminate any duplicates. Once you have that you can compare their sizes, if all three arrays have the same size you are good to go.

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

This answer also ignores the order of elements, as I said, the exact situation happened to me, so maybe someone in the same situation might end up here (as I did).

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



Edit1.

编辑1。

Answering Dmitry Grinko's question: "Why did you use spread operator ( ... ) here - ...new Set ? It doesn't work"

回答 Dmitry Grinko 的问题:“您为什么在这里使用扩展运算符 ( ... ) - ...new Set ?它不起作用”

Consider this code:

考虑这个代码:

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

You'll get

你会得到

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

In order to work with that value you'd need to use some Set properties (see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set). On the other hand, when you use this code:

为了使用该值,您需要使用一些 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)

You'll get

你会得到

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

That's the difference, the former would give me a Set, it would work too as I could get the size of that Set, but the latter gives me the array I need, what's more direct to the resolution.

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

回答by epascarello

On the same lines as JSON.encode is to use join().

在与 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

Only problem is if you care about types which the last comparison tests. If you care about types, you will have to loop.

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

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

If the order should remain the same, than it is just a loop, no sort is needed.

如果顺序应该保持不变,那么它只是一个循环,不需要排序。

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