HOWTO · JavaScript

Wie man zwei Arrays in JavaScript vergleicht

Dieses Tutorial stellt einige Methoden zum Vergleich zweier Arrays in JavaScript vor

Auf dieser Seite

Der JavaScript-Operator === vergleicht Arrays anhand ihrer Identität. Deshalb sind zwei separat erstellte Arrays mit demselben Inhalt bei diesem Vergleich nicht gleich. Um ihre Inhalte zu vergleichen, müssen Sie festlegen, ob die Reihenfolge zählt und wie die Elementwerte verglichen werden. Bei primitiven Werten in gleicher Reihenfolge vergleichen Sie zunächst die Länge und dann jedes entsprechende Element. Verwenden Sie JSON.stringify() nur, wenn dessen Serialisierungsregeln zu Ihren Daten passen. Ist die Reihenfolge unerheblich, vergleichen Sie sortierte Kopien. Diese grundlegenden Ansätze vergleichen verschachtelte Arrays und Objekte anhand ihrer Referenz, nicht ihrer Struktur.

Was bedeutet es, wenn zwei Arrays gleich sind?

Legen Sie zunächst fest, was „gleich“ für Ihre Aufgabe bedeutet. Bei einem geordneten Vergleich müssen die Arrays dieselbe Länge haben und an jedem Index übereinstimmen. Bei einem Vergleich ohne Berücksichtigung der Reihenfolge werden die Arrays als Sammlungen behandelt. Dabei müssen jedoch auch doppelte Werte berücksichtigt werden: [1, 1, 2] ist nicht gleich [1, 2, 2], nur weil beide dieselben unterschiedlichen Werte enthalten.

Entscheiden Sie außerdem, ob die Elementgleichheit flach oder strukturell geprüft werden soll. Für den Vergleich primitiver Werte wie Zahlen und Zeichenfolgen eignet sich die strikte Gleichheit. Bei Objekten und verschachtelten Arrays prüft sie, ob beide Positionen auf dasselbe Objekt verweisen. Eigenschaften und verschachtelte Inhalte werden dabei nicht verglichen.

Arrays mit einer Schleife oder Array.prototype.every() geordnet vergleichen

Eine eigenständige Funktion vermeidet Änderungen am eingebauten Array.prototype. Diese Variante prüft zuerst die Länge und vergleicht dann die entsprechenden Werte mit strikter Gleichheit. Der Vergleich berücksichtigt die Reihenfolge, ist aber flach.

Führen Sie dieses Beispiel aus:

Der Code und die angezeigten Bezeichnungen oder Ausgaben in diesem Abschnitt bleiben auf Englisch.

function arraysEqual(left, right) {
  if (left.length !== right.length) return false;
  return left.every((value, index) => value === right[index]);
}

const first = ["red", "green", "blue"];
const second = ["red", "green", "blue"];
console.log(arraysEqual(first, second));
true

Die Funktion weist auch einen geänderten Wert und eine abweichende Länge zurück. Die folgenden zusätzlichen Aufrufe sind nicht ausgeführte Beispiele:

function arraysEqual(left, right) {
  if (left.length !== right.length) return false;
  return left.every((value, index) => value === right[index]);
}

console.log(arraysEqual(["red", "green"], ["red", "blue"]));
console.log(arraysEqual(["red", "green"], ["red", "green", "blue"]));

Der erste Aufruf ergibt false, weil sich die zweiten Elemente unterscheiden. Der zweite ergibt false, weil die Arrays unterschiedlich lang sind.

Eine for-Schleife kann dieselbe Regel umsetzen, wenn Sie den Vergleich an jedem Index anpassen möchten: Weisen Sie unterschiedliche Längen zurück, geben Sie beim ersten Unterschied false zurück und liefern Sie true, wenn alle Positionen übereinstimmen. Array.prototype.every() ist kompakter und beendet den Durchlauf, sobald der Callback false zurückgibt. In dünn besetzten Arrays überspringt die Methode nicht belegte Positionen. Deshalb kann ihr Ergebnis bei solchen Arrays von dem einer Schleife abweichen, die jeden Index abfragt. Verwenden Sie dichte Arrays oder legen Sie eine Regel für Lücken fest, falls dieser Unterschied relevant ist.

Arrays mit JSON.stringify() vergleichen

Bei Arrays mit JSON-kompatiblen Werten ist der Vergleich ihrer serialisierten Formen kompakt: JSON.stringify(left) === JSON.stringify(right). Die Reihenfolge wird berücksichtigt; [1, 2] und [2, 1] ergeben daher unterschiedliche Vergleiche. Die Serialisierung folgt außerdem bestimmten Regeln: Nicht unterstützte Werte wie undefined werden in einem Array als null serialisiert, während Objekteigenschaften mit dem Wert undefined ausgelassen werden. Unterschiedliche Objekte mit gleichwertigen serialisierbaren Eigenschaften können dieselbe Zeichenfolge ergeben. Das ist jedoch keine allgemeingültige Definition tiefer Gleichheit. Auch die Reihenfolge der Eigenschaften und benutzerdefiniertes Serialisierungsverhalten können das Ergebnis beeinflussen. Verwenden Sie diese Methode nur, wenn ihre Regeln zum Datenvertrag passen. Sie ist weder ein universeller Gleichheitstest noch ist belegt, dass sie bei größeren Arrays schneller ist.

Arrays unabhängig von der Reihenfolge vergleichen

Wenn die Reihenfolge keine Rolle spielt und die Elemente primitive Werte sind, sortieren Sie flache Kopien und vergleichen die resultierenden Positionen. Ein direkter Aufruf von sort() würde die Eingabearrays verändern. Erstellen Sie deshalb zuerst mit slice() Kopien. Die Standardsortierung vergleicht Zeichenfolgendarstellungen. Wenn die Werte anders geordnet werden müssen, etwa Zahlen, geben Sie eine Vergleichsfunktion an. Das Sortieren verursacht zusätzlichen Aufwand; bei gemischten Typen ist eine ausdrückliche Sortierregel nötig. Die Prüfung von Länge und Elementen berücksichtigt weiterhin die Anzahl doppelter Werte.

Bei primitiven Zeichenfolgen sortieren Sie Kopien und vergleichen die resultierenden Werte mit strikter Gleichheit. Dieses vollständige, nicht ausgeführte Beispiel gibt das Vergleichsergebnis und beide ursprünglichen Arrays aus:

Der Code und die angezeigten Bezeichnungen oder Ausgaben in diesem Abschnitt bleiben auf Englisch.

function arraysHaveSameValues(left, right) {
  if (left.length !== right.length) return false;
  const sortedLeft = left.slice().sort();
  const sortedRight = right.slice().sort();
  return sortedLeft.every((value, index) => value === sortedRight[index]);
}

const left = ["pear", "apple", "pear"];
const right = ["pear", "pear", "apple"];
console.log(arraysHaveSameValues(left, right));
console.log(left);
console.log(right);

Bei diesen Arrays ergibt die Vergleichsregel true, und durch das Sortieren der Kopien bleibt die Reihenfolge beider Eingaben unverändert. Werden beide Kopien sortiert und anschließend alle Positionen verglichen, bleibt auch die Anzahl doppelter Werte relevant: Arrays mit unterschiedlich vielen Vorkommen eines Werts stimmen nicht überein. Die Standardsortierung und die strikte Gleichheit in diesem Beispiel sind für Zeichenfolgen gedacht. Bei gemischten Werten benötigen Sie eine zu ihren Typen passende Vergleichs- und Gleichheitsregel. Legen Sie bei Objekten einen Schlüssel fest, der die gewünschte Gleichheit abbildet, oder verwenden Sie eine passende Zuordnungsstrategie. Die Standardsortierung bestimmt keine Objektgleichheit.

Verschachtelte Arrays und Objekte behandeln

Die Beispiele für geordnete Vergleiche und Sortierungen verwenden für jedes Element strikte Gleichheit. Zwei separat erstellte Werte wie [{ id: 1 }] gelten an dieser Position daher als ungleich, obwohl ihre sichtbaren Eigenschaften übereinstimmen. Dasselbe gilt für verschachtelte Arrays. Wenn strukturelle Gleichheit erforderlich ist, verwenden Sie einen rekursiven Vergleich, der das Verhalten für jeden unterstützten Typ festlegt, oder eine für die Anwendung geeignete Bibliothek für tiefe Gleichheit. Klären Sie vorab, wie Datumsangaben, Maps, Sets, Prototypen, Zyklen und besondere numerische Werte behandelt werden sollen. Verschiedene Werkzeuge für tiefe Gleichheit können unterschiedliche Regeln umsetzen.

Bei Daten, von denen bekannt ist, dass sie JSON-kompatibel sind, kann die Serialisierung manchmal einen kompakten strukturellen Vergleich ermöglichen; dabei gelten die oben beschriebenen Einschränkungen. Machen Sie andernfalls den Gleichheitsvertrag ausdrücklich und prüfen Sie die für die Anwendung relevanten Fälle. Wählen Sie in der Praxis die einfachste Methode, die zur benötigten Reihenfolge und Wertsemantik passt: every() oder eine Schleife für geordnete primitive Werte, Serialisierung für passend eingeschränkte JSON-Daten und eine bewusst gewählte Zuordnungs- oder Tiefgleichheitsstrategie für andere Anforderungen.