it-swarm.com.de

Wie kann man Arrays in JavaScript vergleichen?

Ich möchte zwei Arrays miteinander vergleichen ... idealerweise effizient. Nichts Besonderes, nur true, wenn sie identisch sind, und false, falls nicht. Es überrascht nicht, dass der Vergleichsoperator nicht funktioniert.

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-Codierung für jedes Array ist ein Muss. Aber gibt es eine schnellere oder "bessere" Möglichkeit, Arrays einfach zu vergleichen, ohne jeden Wert durchlaufen zu müssen?

762
Julian H. Lam

Um Arrays zu vergleichen, durchlaufen Sie sie und vergleichen Sie jeden Wert: 

Arrays vergleichen:

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

Verwendungszweck:

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

Sie können sagen "Aber es ist viel schneller, Strings zu vergleichen - keine Schleifen ..." Erste rekursive Schleife, die Array in String konvertiert, und zweite, die zwei Strings vergleicht. Diese Methode ist also schneller als die Verwendung von Zeichenfolge.

Ich glaube, dass größere Datenmengen immer in Arrays gespeichert werden sollten, nicht in Objekten. Wenn Sie jedoch Objekte verwenden, können diese auch teilweise verglichen werden.
Hier ist wie:

Objekte vergleichen:

Ich habe oben gesagt, dass zwei Objekte instance niemals gleich sein werden, selbst wenn sie im Moment die gleichen Daten enthalten:

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

Dies hat einen Grund, da es zum Beispiel private Variablen in Objekten geben kann.

Wenn Sie jedoch nur die Objektstruktur verwenden, um Daten zu enthalten, ist der Vergleich noch möglich:

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

Denken Sie jedoch daran, dass dies zum Vergleich von JSON-ähnlichen Daten und nicht von Klasseninstanzen und anderen Dingen dienen soll. Wenn Sie mehr komplizierte Objekte vergleichen möchten, sehen Sie diese Antwort und ihre überlange Funktion .
.__ Damit dies mit Array.equals funktioniert, müssen Sie die ursprüngliche Funktion ein wenig bearbeiten:

...
    // 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]) {
...

Ich habe ein kleines Testwerkzeug für beide Funktionen erstellt.

Bonus: Verschachtelte Arrays mit indexOf und contains

Samy Bencherif hat nützliche Funktionen für den Fall vorbereitet, dass Sie in verschachtelten Arrays nach einem bestimmten Objekt suchen, das hier verfügbar ist: https://jsfiddle.net/SamyBencherif/8352y6yw/

780
Tomáš Zato

Dies funktioniert zwar nur für skalare Arrays (siehe Hinweis unten), ist jedoch kurz:

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

Rr, in ECMAScript 6/CoffeeScript/TypeScript mit Pfeilfunktionen:

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

(Hinweis: "Skalar" bedeutet hier Werte, die direkt mit === verglichen werden können. Also: Zahlen, Strings, Objekte nach Referenz, Funktionen nach Referenz. Weitere Informationen zu den Vergleichsoperatoren finden Sie unter die MDN-Referenz .

UPDATE

Nach dem, was ich aus den Kommentaren gelesen habe, kann das Sortieren des Arrays und das Vergleichen zu einem genauen Ergebnis führen:

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

Z.B:

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

Dann würde der obige Code true geben

286
user2782196

Ich benutze die Underscore-Bibliothek gerne für Array-/Objekt-schwere Codierungsprojekte ... In Underscore und Lodash, egal ob Sie Arrays oder Objekte vergleichen, es sieht einfach so aus:

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

Ich denke, dies ist der einfachste Weg, dies mit JSON stringify zu tun, und es kann in einigen Situationen die beste Lösung sein:

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

Dadurch werden die Objekte a1 und a2 in Strings umgewandelt, damit sie miteinander verglichen werden können. Die Reihenfolge ist in den meisten Fällen wichtig, da das Objekt mithilfe eines Sortieralgorithmus sortiert werden kann, der in einer der obigen Antworten angezeigt wird.

Bitte beachten Sie, dass Sie nicht mehr das Objekt, sondern die Zeichenfolgendarstellung des Objekts vergleichen. Es kann nicht genau das sein, was Sie wollen.

81
radtek

Es ist unklar, was Sie mit "identisch" meinen. Sind beispielsweise die Arrays a und b identisch (beachten Sie die verschachtelten Arrays)?

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

Hier ist eine optimierte Array-Vergleichsfunktion, die die entsprechenden Elemente jedes Arrays unter Verwendung strenger Gleichheit miteinander vergleicht und keinen rekursiven Vergleich von Array-Elementen vornimmt, die selbst Arrays sind. Dies bedeutet, dass im obigen Beispiel arraysIdentical(a, b)false zurückgeben würde. Es funktioniert im allgemeinen Fall, dass JSON- und join()-basierte Lösungen nicht:

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;
};
61
Tim Down

Der praktische Weg

Ich finde es falsch zu sagen, dass eine bestimmte Implementierung "The Right Way ™" ist, wenn sie im Gegensatz zu einer "falschen" Lösung nur "richtig" ("richtig") ist. Die Lösung von Tomáš ist eine deutliche Verbesserung gegenüber dem stringbasierten Array-Vergleich, aber das bedeutet nicht, dass es objektiv "richtig" ist. Was ist überhaupt richtig ? Ist es das schnellste? Ist es das flexibelste? Ist es am einfachsten zu verstehen? Ist es das schnellste Debugging? Verwendet es die wenigsten Operationen? Hat es irgendwelche Nebenwirkungen? Keine Lösung kann das Beste von allem haben.

Tomás könnte sagen, dass seine Lösung schnell ist, aber ich würde auch sagen, dass sie unnötig kompliziert ist. Es wird versucht, eine All-in-One-Lösung zu sein, die für alle geschachtelten oder nicht geschachtelten Arrays funktioniert. Tatsächlich akzeptiert es sogar mehr als nur Arrays als Eingabe und versucht dennoch, eine "gültige" Antwort zu geben.


Generika bieten Wiederverwendbarkeit

Meine Antwort wird das Problem anders angehen. Ich beginne mit einer generischen arrayCompare Prozedur, die sich nur mit dem Durchlaufen der Arrays befasst. Von dort aus bauen wir unsere anderen grundlegenden Vergleichsfunktionen wie arrayEqual und arrayDeepEqual usw

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

Meiner Meinung nach benötigt die beste Art von Code nicht einmal Kommentare, und dies ist keine Ausnahme. Hier passiert so wenig, dass Sie das Verhalten dieses Verfahrens fast mühelos nachvollziehen können. Sicher, ein Teil der ES6-Syntax scheint Ihnen jetzt fremd zu sein, aber das liegt nur daran, dass ES6 relativ neu ist.

Wie der Typ andeutet, übernimmt arrayCompare die Vergleichsfunktion f und zwei Eingabearrays xs und ys. Zum größten Teil rufen wir nur f (x) (y) für jedes Element in den Eingabearrays auf. Wir geben ein frühes false zurück, wenn das benutzerdefinierte ffalse zurückgibt - dank der Kurzschlussauswertung von &&. Ja, dies bedeutet, dass der Komparator die Iteration vorzeitig beenden und verhindern kann, dass der Rest des Eingabearrays durchlaufen wird, wenn dies nicht erforderlich ist.


Strenger Vergleich

Als nächstes können wir mit unserer Funktion arrayCompare auf einfache Weise andere Funktionen erstellen, die wir möglicherweise benötigen. Wir beginnen mit dem elementaren 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

So einfach ist das. arrayEqual kann mit arrayCompare und einer Komparatorfunktion definiert werden, die a mit b unter Verwendung von === vergleicht (für strikte Gleichheit).

Beachten Sie, dass wir equal auch als eigene Funktion definieren. Dies unterstreicht die Rolle von arrayCompare als Funktion höherer Ordnung, um unseren Komparator erster Ordnung im Kontext eines anderen Datentyps (Array) zu verwenden.


Loser Vergleich

Genauso einfach könnten wir arrayLooseEqual mit einem == Definieren. Wenn Sie nun 1 (Zahl) mit '1' (Zeichenfolge) vergleichen, lautet das Ergebnis 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

Tiefer Vergleich (rekursiv)

Sie haben wahrscheinlich bemerkt, dass dies nur ein flacher Vergleich ist. Sicher ist Tomás 'Lösung "The Right Way ™", weil es einen tiefen Vergleich impliziert, oder?

Nun, unser arrayCompare -Verfahren ist vielseitig genug, um einen tiefen Gleichheitstest zum Kinderspiel zu machen ...

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

So einfach ist das. Wir bauen einen tiefen Komparator mit einer anderen Funktion höherer Ordnung. Diesmal verpacken wir arrayCompare mit einem benutzerdefinierten Komparator, der überprüft, ob a und b Arrays sind. Wenn ja, wende arrayDeepCompare erneut an, andernfalls vergleiche a und b mit dem benutzerdefinierten Komparator (f). Dies ermöglicht es uns, das tiefe Vergleichsverhalten von dem tatsächlichen Vergleich der einzelnen Elemente zu trennen. Dh, wie das obige Beispiel zeigt, können wir mit equal, looseEqual oder einem anderen Vergleicher, den wir erstellen, tiefgehend vergleichen.

Da arrayDeepCompare Currys ist, können wir es teilweise anwenden, wie wir es auch in den vorherigen Beispielen getan haben

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

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

Für mich ist dies bereits eine deutliche Verbesserung gegenüber Tomás 'Lösung, da ich je nach Bedarf explizit einen flachen oder tiefen Vergleich für meine Arrays wählen kann.


Objektvergleich (Beispiel)

Was ist nun, wenn Sie eine Reihe von Objekten oder etwas haben? Vielleicht möchten Sie diese Arrays als "gleich" betrachten, wenn jedes Objekt den gleichen id Wert hat ...

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

So einfach ist das. Hier habe ich Vanilla JS-Objekte verwendet, aber diese Art von Komparator könnte für jeden Objekttyp funktionieren; sogar Ihre benutzerdefinierten Objekte. Die Lösung von Tomáš müsste komplett überarbeitet werden, um diese Art von Gleichstellungstest zu unterstützen

Tiefes Array mit Objekten? Kein Problem. Wir haben äußerst vielseitige generische Funktionen entwickelt, damit sie in einer Vielzahl von Anwendungsfällen eingesetzt werden können.

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

Beliebiger Vergleich (Beispiel)

Oder was, wenn Sie eine andere Art von völlig willkürlichem Vergleich machen wollten? Vielleicht möchte ich wissen, ob jeder x größer ist als jeder 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

Weniger ist mehr

Sie können sehen, dass wir mit weniger Code tatsächlich mehr erreichen. An arrayCompare selbst ist nichts kompliziert, und jeder der von uns erstellten benutzerdefinierten Komparatoren ist sehr einfach zu implementieren.

Mit Leichtigkeit können wir genau definieren, wie zwei Arrays verglichen werden sollen - flach, tief, streng, locker, eine Objekteigenschaft oder eine willkürliche Berechnung oder eine beliebige Kombination davon - alle unter Verwendung einer Prozedur =, arrayCompare. Vielleicht kannst du dir sogar einen RegExp Komparator ausdenken! Ich weiß, wie Kinder diese Regexps lieben ...

Ist es das schnellste? Nee. Aber wahrscheinlich muss es auch nicht sein. Wenn Geschwindigkeit die einzige Metrik ist, mit der die Qualität unseres Codes gemessen wird, werden viele wirklich großartige Codes weggeworfen. Deshalb nenne ich diesen Ansatz The Practical Way. Oder vielleicht um fairer zu sein, [~ # ~] ein [~ # ~] praktischer Weg. Diese Beschreibung ist für diese Antwort geeignet, da ich nicht sage, dass diese Antwort nur im Vergleich zu einer anderen Antwort praktisch ist. es ist objektiv wahr. Wir haben ein hohes Maß an Praktikabilität mit sehr wenig Code erreicht, über den man sehr leicht nachdenken kann. Kein anderer Code kann sagen, dass wir diese Beschreibung nicht verdient haben.

Ist das die "richtige" Lösung für Sie? Das liegt an Ihnen zu entscheiden. Und niemand anderes kann das für Sie tun. Nur Sie wissen, was Sie brauchen. In fast allen Fällen schätze ich einfachen, praktischen und vielseitigen Code gegenüber cleveren und schnellen. Was Sie schätzen, kann davon abweichen. Wählen Sie also, was für Sie funktioniert.


Bearbeiten

Meine alte Antwort konzentrierte sich mehr auf die Zerlegung von arrayEqual in winzige Prozeduren. Es ist eine interessante Übung, aber nicht der beste (praktischste) Weg, um dieses Problem anzugehen. Wenn Sie interessiert sind, können Sie diesen Versionsverlauf anzeigen.

50
user633183

Im Geiste der ursprünglichen Frage:

Ich möchte zwei Arrays vergleichen ... idealerweise effizient. Nichts Phantasie, nur wahr, wenn sie identisch sind, und falsch, wenn nicht.

Ich habe Leistungstests für einige der hier vorgeschlagenen einfacheren Vorschläge mit den folgenden Ergebnissen (schnell bis langsam) durchgeführt:

while (67%) von Tim Down

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

alle (69%) vom Benutzer2782196

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

reduzieren Sie (74%) durch DEIs

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

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

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

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

half toString (90%) von Victor Palomo

a1 == a2.toString();

stringify (100%) von radtek

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

Note In den folgenden Beispielen wird davon ausgegangen, dass die Arrays sortierte eindimensionale Arrays sind. Der .length-Vergleich wurde für einen gemeinsamen Benchmark entfernt (fügen Sie a1.length === a2.length zu einem der Vorschläge hinzu und Sie erhalten eine Leistungssteigerung von ~ 10%). Wählen Sie die Lösung, die für Sie am besten geeignet ist, und wissen Sie, wie schnell und begrenzt jede ist.

Unbezogene Anmerkung: Es ist interessant zu sehen, wie die Leute den auslöserischen John Waynes über den Down-Voting-Button bei absolut legitimen Antworten auf diese Frage erhalten. 

35
unitario

Wenn ich Tomáš Zatos Antwort aufbaue, stimme ich zu, dass das Durchlaufen der Arrays das schnellste ist. Außerdem sollte die Funktion (wie andere bereits erwähnt haben) gleich/gleich heißen, nicht vergleichen. In Anbetracht dessen habe ich die Funktion geändert, um den Vergleich von Arrays auf Ähnlichkeit zu handhaben - d. H. Sie haben die gleichen Elemente, aber außer Ordnung - für den persönlichen Gebrauch, und ich dachte, ich würde sie hierher werfen, damit jeder sie sehen kann.

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

Diese Funktion verwendet einen zusätzlichen Parameter von strict, der standardmäßig auf true festgelegt ist. Dieser strikte Parameter definiert, ob die Arrays sowohl in Inhalt als auch in der Reihenfolge dieser Inhalte völlig gleich sein müssen oder einfach nur den gleichen Inhalt enthalten.

Beispiel:

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

Ich habe auch ein kurzes jsfiddle mit der Funktion und diesem Beispiel geschrieben:
http://jsfiddle.net/Roundaround/DLkxX/

28

Auch wenn dies viele Antworten hat, von denen ich glaube, dass sie hilfreich sind:

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

In der Frage wird nicht angegeben, wie die Struktur des Arrays aussehen wird. Wenn Sie also sicher sind, dass Sie keine verschachtelten Arrays oder Objekte in Ihrem Array haben (es ist mir passiert, deshalb kam ich zu dieser Antwort) der obige Code wird funktionieren.

Was passiert, ist, dass wir Spread-Operator (...) verwenden, um beide Arrays zusammenzuführen, und dann Set verwenden, um alle Duplikate zu entfernen. Sobald Sie das haben, können Sie deren Größen vergleichen. Wenn alle drei Arrays die gleiche Größe haben, können Sie loslegen.

Diese Antwort auch ignoriert die Reihenfolge der Elemente, wie gesagt, die genaue Situation ist mir passiert, so dass vielleicht jemand in derselben Situation hier landen könnte (wie ich).


Edit1.

Beantwortung der Frage von Dmitry Grinko: "Warum haben Sie den Spread-Operator (...) hier - ... neues Set verwendet? Es funktioniert nicht"

Betrachten Sie diesen Code:

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

Du wirst kriegen

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

Um mit diesem Wert arbeiten zu können, müssen Sie einige Set-Eigenschaften verwenden (siehe https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set ) .. Wenn Sie jedoch diesen Code verwenden:

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

Du wirst kriegen

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

Das ist der Unterschied, der erstere würde mir ein Set geben, es würde auch funktionieren, da ich die Größe dieses Sets bekommen könnte, aber das letztere gibt mir das Array, das ich brauche, was die Auflösung direkter macht.

8

In den gleichen Zeilen wie JSON.encode soll join () verwendet werden.

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

Das einzige Problem ist, wenn Sie sich für Typen interessieren, die beim letzten Vergleich getestet wurden.

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

Wenn die Reihenfolge gleich bleiben soll, als nur eine Schleife, ist keine Sortierung erforderlich.

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

Wenn es sich nur um zwei Arrays von Zahlen oder Strings handelt, handelt es sich um ein schnelles einzeiliges Array

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
6
Gaizka Allende

für eindimensionale Arrays können Sie einfach Folgendes verwenden:

arr1.sort().toString() == arr2.sort().toString()

dies kümmert sich auch um Arrays mit nicht übereinstimmendem Index.

5
Vivek

Wenn Sie ein Testframework wie Mocha mit der Assertionsbibliothek Chai verwenden, können Sie mit der Gleichheit deep Arrays vergleichen.

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

Dies sollte nur dann true zurückgegeben werden, wenn die Arrays bei entsprechenden Indizes gleiche Elemente aufweisen.

5
metakermit

Hier ist eine TypeScript-Version:

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

Einige Testfälle für Mokka:

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)
})
4
Esqarrouth

Dies vergleicht 2 unsortierte Arrays:

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

Herers meine Lösung:

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

Funktioniert mit jeder geschachtelten Datenstruktur und ignoriert offensichtlich die Methoden der Objekte. Denken Sie nicht einmal daran, Object.prototype mit dieser Methode zu erweitern, als ich dies einmal probiert habe, brach jQuery;)

Für die meisten Arrays ist es immer noch schneller als die meisten Serialisierungslösungen. Dies ist wahrscheinlich die schnellste Vergleichsmethode für Arrays von Objektdatensätzen.

3
Harry

Wir könnten dies auf funktionale Weise tun, indem wir every verwenden ( https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/Array/every ).

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
3
peonicles
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);

////// OR ///////

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)
2
Vasanth

Ich glaube an einfaches JS und an ECMAScript 2015, was süß und einfach zu verstehen ist.

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

}

hoffe es hilft jemandem.

1
ArifMustafa

Vergleich von 2 Arrays:

var arr1 = [1,2,3];
var arr2 = [1,2,3];

function compare(arr1,arr2)
{
  if((arr1 == arr2) && (arr1.length == arr2.length))
    return true;
  else
    return false;
}

aufrufende Funktion

var isBool = compare(arr1.sort().join(),arr2.sort().join());
1
Amay Kulkarni

Wählen Sie jeweils eine unter [a] aus, und wiederholen Sie alle durch [b]:

var a = [1,4,5,9];
var b = [1,6,7,5];

for (i = 0; i < a.length; i++) {
    for (z = 0; z < a.length; z++) {
        if (a[i] === b[z]) {
            console.log(b[z]); // if match > console.log it 
        }
    }
}
1
jclobro

Der Grund ist der identische oder strikte Operator (===), der mit keiner Typumwandlung verglichen wird. Wenn also beide Werte nicht denselben Wert und denselben Typ haben, werden sie nicht als gleich betrachtet.

werfen Sie einen Blick auf diesen Link, der Sie zweifelsfrei macht auf einfache Weise zu verstehen, wie der Identitätsoperator funktioniert

1
ludico8

dieses Skript vergleicht Object, Arrays und mehrdimensionale Arrays

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

die erste Zeile prüft, ob es sich um einen primitiven Typ handelt. Wenn ja, vergleicht er die beiden Parameter.

wenn sie Objekte sind. Es iteriert über das Objekt und überprüft jedes Element rekursiv. 

Verwendungszweck:

var a=[1,2,[1,2]];
var b=[1,2,[1,2]];
var isEqual=compare(a,b);  //true
1
Omar Elawady

Diese Funktion vergleicht zwei Arrays mit beliebiger Form und Dimesionalität:

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

Ihr Code wird den Fall nicht angemessen behandeln, wenn beide Arrays dieselben Elemente, jedoch nicht in derselben Reihenfolge haben.

Schauen Sie sich meinen Code mit Ihrem Beispiel an, das zwei Arrays vergleicht, deren Elemente Zahlen sind. Sie können ihn für andere Elementtypen ändern oder erweitern (indem Sie .join () anstelle von .toString () verwenden).

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);
1
durga patra

In meinem Fall enthalten verglichene Arrays nur Zahlen und Strings. Diese Funktion zeigt Ihnen, ob Arrays die gleichen Elemente enthalten.

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

Lass es uns testen!

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
1
yesnik

Erweiterung der Idee von Tomáš Zato. Tomas's Array.prototype.compare sollte eigentlich Array.prototype.compareIdentical heißen.

Es gibt weiter:

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

Aber scheitert an:

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

Hier ist (meiner Meinung nach) bessere Version:

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/

1
Igor S.

Ein anderer Ansatz mit sehr wenig Code (Verwendung von Array verkleinern und Array enthält ):

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

Wenn Sie auch die Gleichheit der Bestellung vergleichen wollen:

arr1.length == arr2.length && arr1.reduce((a, b, i) => a && arr2[i], true)
  • Die length-Prüfung stellt sicher, dass die Menge der Elemente in einem Array nicht nur eine Teilmenge des anderen ist.

  • Der Reduzierer wird verwendet, um durch ein Array zu gehen und nach jedem Element in einem anderen Array zu suchen. Wenn ein Element nicht gefunden wird, gibt die Reduzierungsfunktion false zurück. 

    1. Im ersten Beispiel wird getestet, dass ein Element enthalten ist
    2. Das zweite Beispiel prüft auch die Bestellung
1
DEls
JSON.stringify(collectionNames).includes(JSON.stringify(sourceNames)) ?  array.Push(collection[i]) : null

So habe ich es gemacht.

1
Leed

Mit einer Option zum Vergleichen der Bestellung oder nicht:

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;
        }
    });
}
0
Lacho Tomov

Rekursiv & arbeitet aufVERSCHACHTELTENArrays:

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"]]]
));;  
0
J.M.I. MADISON
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  
0

Ein einfacher Ansatz:

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;
}
0
Pedro Rodrigues

Meine Lösung vergleicht Objekte, keine Arrays. Dies funktioniert auf die gleiche Weise wie Tomášs, da Arrays Objekte sind, jedoch ohne die Warnung:

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

Ich hoffe, das hilft Ihnen oder jemandem, der nach einer Antwort sucht.

0
user1877408

Rekursive cmp-Funktion, die mit number/string/array/object arbeitet

<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>
0
Daphoque

versuchte tief-gleich und es hat funktioniert

var eq = require('deep-equal');
eq({a: 1, b: 2, c: [3, 4]}, {c: [3, 4], a: 1, b: 2});
0
d9k
function compareArrays(arrayA, arrayB) {
    if (arrayA.length != arrayB.length) return true;
    for (i = 0; i < arrayA.length; i++)
        if (arrayB.indexOf(arrayA[i]) == -1) {
            return true;
        }
    }
    for (i = 0; i < arrayB.length; i++) {
        if (arrayA.indexOf(arrayB[i]) == -1) {
            return true;
        }
    }
    return false;
}
0
macki

Arbeitet mitMULTIPLENArgumenten mitVERSCHACHTELTENArrays:

//: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"   ]]],
));; 
0
J.M.I. MADISON

Ich habe verwendet: um ein Array zu verbinden und eine Zeichenfolge zu erstellen, die verglichen werden soll . Bei Szenarien, die komplexer als in diesem Beispiel sind, können Sie ein anderes Trennzeichen verwenden.

var a1 = [1,2,3];
var a2 = [1,2,3];
if (a1.length !== a2.length) {
   console.log('a1 and a2 are not equal')
}else if(a1.join(':') === a2.join(':')){
   console.log('a1 and a2 are equal')
}else{
   console.log('a1 and a2 are not equal')
}
0
Manoj Yadav

Obwohl die erste Antwort auf diese Frage richtig und gut ist, könnte der bereitgestellte Code einige Verbesserungen erfordern.

Nachfolgend finden Sie meinen eigenen Code zum Vergleichen von Arrays und Objekten. Der Code ist kurz und einfach:

Array.prototype.equals = function(otherArray) {
  if (!otherArray || this.length != otherArray.length) return false;
  return this.reduce(function(equal, item, index) {
    var otherItem = otherArray[index];
    var itemType = typeof item, otherItemType = typeof otherItem;
    if (itemType !== otherItemType) return false;
    return equal && (itemType === "object" ? item.equals(otherItem) : item === otherItem);
  }, true);
};

if(!Object.prototype.keys) {
  Object.prototype.keys = function() {
    var a = [];
    for (var key in this) {
      if (this.hasOwnProperty(key)) a.Push(key);
    }
    return a;
  }
  Object.defineProperty(Object.prototype, "keys", {enumerable: false});
}

Object.prototype.equals = function(otherObject) {
  if (!otherObject) return false;
  var object = this, objectKeys = object.keys();
  if (!objectKeys.equals(otherObject.keys())) return false;
  return objectKeys.reduce(function(equal, key) {
    var value = object[key], otherValue = otherObject[key];
    var valueType = typeof value, otherValueType = typeof otherValue;
    if (valueType !== otherValueType) return false;
    // this will call Array.prototype.equals for arrays and Object.prototype.equals for objects
    return equal && (valueType === "object" ? value.equals(otherValue) : value === otherValue);
  }, true);
}
Object.defineProperty(Object.prototype, "equals", {enumerable: false});

Dieser Code unterstützt Arrays, die in Objekten verschachtelt sind, und Objekte, die in Arrays verschachtelt sind.

Sie können eine vollständige Suite von Tests sehen und den Code selbst unter dieser Antwort testen: https://repl.it/Esfz/3

0
Mator

Hier ist eine CoffeeScript-Version für diejenigen, die das bevorzugen:

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

Alle Credits gehen an @ tomas-zato.

0
Martin

Tatsächlich geben sie in der LodashDokumentation zwei ziemlich gute Beispiele zum Vergleichen und Zurückgeben neuer Arrays für Unterschiede und Ähnlichkeiten (jeweils in den folgenden Beispielen):

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

Wenn Sie nicht immer wissen, welches Array größer sein wird, können Sie eine Hilfsfunktion dafür wie folgt schreiben:

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

Soweit ich weiß, passen diese auch sehr gut zusammen, das ist also ziemlich gut.

Ich weiß, dass es nicht zu begrüßen ist, wenn man sich auf Bibliotheken verlässt, aber dies ist die prägnanteste und sauberste Lösung, die ich für ein wirklich häufiges Problem gefunden habe. Hoffe es hilft jemandem!

0
corysimmons

Hier ist ein sehr kurzer Weg

function arrEquals(arr1, arr2){
     arr1.length == arr2.length && 
     arr1.filter(elt=>arr2.includes(elt)).length == arr1.length
}
0

Einige großartige Antworten. Aber ich möchte andere Ideen teilen, die sich beim Vergleich von Arrays als zuverlässig erwiesen haben. Wir können zwei Arrays mit JSON.stringify () vergleichen. Es erstellt einen String aus dem Array und vergleicht so zwei erhaltene Strings aus zwei Arrays auf Gleichheit

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
AL-zami

Wenn das Array einfach ist und die Reihenfolge wichtig ist, können diese beiden Zeilen hilfreich sein

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

Reduzieren Sie Spaziergänge durch eines von array und geben Sie 'false' zurück, wenn mindestens ein Element von 'a' weder dem Element von 'b' .__ entspricht 

0
Serge