Erfahren Sie, ob zwei Arrays dieselben Werte haben

104

Ich habe diese zwei Arrays: eines ist mit Informationen aus einer Ajax-Anfrage gefüllt und ein anderes speichert die Schaltflächen, auf die der Benutzer klickt. Ich benutze diesen Code (ich habe mit Probennummern gefüllt):

var array1 = [2, 4];
var array2 = [4, 2]; //It cames from the user button clicks, so it might be disordered.
array1.sort(); //Sorts both Ajax and user info.
array2.sort();
if (array1==array2) {
    doSomething();
}else{
    doAnotherThing();
}

Aber es gibt immer false, auch wenn die beiden Arrays gleich sind, aber mit unterschiedlichen Namen. (Ich habe dies in der JS-Konsole von Chrome überprüft.) Kann ich also auf irgendeine Weise wissen, ob diese beiden Arrays dasselbe enthalten? Warum gibt es false? Wie kann ich wissen, welche Werte im ersten Array nicht im zweiten enthalten sind?

Carlos Precioso
quelle
1
Ich bin mir ziemlich sicher, dass Sie jedes Element der Arrays durchgehen müssen.
Thomas Li
Wissen Sie, warum es falsch zurückgibt? Neugierig.
RobW
Siehe @ Andrews Antwort stackoverflow.com/a/6229263/702565
Carlos Precioso

Antworten:

36
function arraysEqual(_arr1, _arr2) {

    if (!Array.isArray(_arr1) || ! Array.isArray(_arr2) || _arr1.length !== _arr2.length)
      return false;

    var arr1 = _arr1.concat().sort();
    var arr2 = _arr2.concat().sort();

    for (var i = 0; i < arr1.length; i++) {

        if (arr1[i] !== arr2[i])
            return false;

    }

    return true;

}

Beachten Sie, dass dies die ursprünglichen Arrays im Gegensatz zu einer vorherigen Antwort nicht ändert.

Maciej Krawczyk
quelle
2
Das Sortieren dauert nlog (n). Sie müssen nicht sortieren. Diese Antwort stackoverflow.com/a/55614659/3209523 arbeitet in linearer Zeit.
Canbax
Bei Verwendung von Typoskript verursachte Array.isArray () Fehler und beseitigte, dass es einwandfrei funktionierte.
Ariel Frischer
88

Wenn Ihre Array-Elemente keine Objekte sind - wenn es sich beispielsweise um Zahlen oder Zeichenfolgen handelt, können Sie die verknüpften Zeichenfolgen vergleichen, um festzustellen, ob sie in beliebiger Reihenfolge dieselben Mitglieder haben.

var array1= [10, 6, 19, 16, 14, 15, 2, 9, 5, 3, 4, 13, 8, 7, 1, 12, 18, 11, 20, 17];
var array2= [12, 18, 20, 11, 19, 14, 6, 7, 8, 16, 9, 3, 1, 13, 5, 4, 15, 10, 2, 17];

if(array1.sort().join(',')=== array2.sort().join(',')){
    alert('same members');
}
else alert('not a match');
kennebec
quelle
2
Dies funktioniert gut für Grundelemente oder Objekte, die toString-Werte eindeutig identifizieren, jedoch nicht für beliebige Objekte.
Devios1
Vielen Dank! saubere Lösung
Gaston Sanchez
3
Achten Sie auf Nullelemente und Sortierung. Am Ende hatte ich in meinem Fall Zeichenfolgen wie ", 2,2,3" und "2,2,3", die natürlich nicht genau gleich sind.
barbara.post
2
Könnte für Zeichenfolgen fehlschlagen, dh ['a', 'b']und ['a,b']. Ich würde diese Technik nur für kleine Wegwerfskripte empfehlen.
Alex
1
@alex - In meinem Fall sind Kommas in Zeichenfolgen zulässig, Semikolons jedoch nicht. Deshalb habe ich ';' statt Komma beitreten
a2345sooted
45

Wenn Sie nur überprüfen möchten, ob zwei Arrays dieselben Werte haben (unabhängig von der Anzahl der Vorkommen und der Reihenfolge der einzelnen Werte), können Sie dies mithilfe von lodash tun :

_.isEmpty(_.xor(array1, array2))

Kurz, einfach und hübsch!

Technotronic
quelle
1
Ich kann nicht scheinen, xorin den Unterstrich-Dokumenten zu finden ? Denkst du an IODash?
Patrick Mencias-Lewis
44
Array.prototype.compare = function(testArr) {
    if (this.length != testArr.length) return false;
    for (var i = 0; i < testArr.length; i++) {
        if (this[i].compare) { //To test values in nested arrays
            if (!this[i].compare(testArr[i])) return false;
        }
        else if (this[i] !== testArr[i]) return false;
    }
    return true;
}

var array1 = [2, 4];
var array2 = [4, 2];
if(array1.sort().compare(array2.sort())) {
    doSomething();
} else {
    doAnotherThing();
}

Vielleicht?

isakkarlsson
quelle
Danke dir! Es funktioniert genau wie gewünscht. Ich habe die Funktion ein wenig geändert, damit ich auch wissen kann, wie viele Fehlanpassungen es gibt.
Carlos Precioso
falsch für [2,4] [4,2].
Suraz Khanal
@ SurazKhanal müssen noch sortieren
Aaron McMillin
26

Warum Ihr Code nicht funktioniert hat

JavaScript hat primitive Datentypen und nicht-primitive Datentypen.

Für primitive Datentypen, ==und ===prüfen , ob die Dinge , die auf beiden Seiten der Stäbe haben den gleichen Wert. Deshalb1 === 1 ist es wahr.

Für nicht-primitive Datentypen wie Arrays ==und ===Kontrolle Referenz Gleichheit. Das heißt, sie prüfen, ob arr1und arr2dasselbe Objekt sind. In Ihrem Beispiel haben die beiden Arrays dieselben Objekte in derselben Reihenfolge, sind jedoch nicht gleichwertig.

Lösungen

Zwei Arrays arr1und arr2haben genau dann dieselben Mitglieder, wenn:

  • Alles in arr2ist inarr1

UND

  • Alles in arr1ist inarr2

Das reicht also aus (ES2016):

const containsAll = (arr1, arr2) => 
                arr2.every(arr2Item => arr1.includes(arr2Item))

const sameMembers = (arr1, arr2) => 
                        containsAll(arr1, arr2) && containsAll(arr2, arr1);

sameMembers(arr1, arr2); // `true`

Diese zweite Lösung mit Underscore entspricht eher dem, was Sie versucht haben:

arr1.sort();
arr2.sort();

_.isEqual(arr1, arr2); // `true`

Es funktioniert, weil isEqualnach "tiefer Gleichheit" gesucht wird, was bedeutet, dass mehr als nur Referenzgleichheit betrachtet und Werte verglichen werden.

Eine Lösung für Ihre dritte Frage

Sie haben auch gefragt, wie Sie herausfinden können, in welchen Dingen arr1nichts enthalten istarr2 .

Dies wird es tun (ES2015):

const arr1 = [1, 2, 3, 4];
const arr2 = [3, 2, 1];

arr1.filter(arr1Item => !arr2.includes(arr1Item)); // `[4]`

Sie können auch die differencefolgende Methode verwenden:

_.difference(arr1, arr2); // `[4]`

AKTUALISIEREN

Siehe @ Redu's Kommentar - meine Lösung ist für sameMembers, aber was Sie vielleicht im Sinn haben, ist sameMembersInOrderauch bekannt als deepEquals.

UPDATE 2

Wenn Sie sich nicht um die Reihenfolge der Mitglieder der Arrays kümmern, ist ES2015 + Setmöglicherweise eine bessere Datenstruktur als Array. LesenisSupersetdifference Sie die MDN-Hinweise zur Implementierung und Verwendung gefährlicher Affen-Patches.

Max Heiber
quelle
1
Ihre Lösungen sind falsch. "Zwei Arrays, arr1 und arr2, haben genau dann dieselben Mitglieder, wenn: Alles in arr2 ist in arr1 UND alles in arr1 ist in arr2" Dies ist auch falsch. Dies ist ein Array, keine Menge. Sollte also sameMembers([1,1,2],[2,1,2]);false zurückgeben.
Reduzieren Sie den
1
@Redu denke, es hängt davon ab, was "gleiche Mitglieder" bedeuten - ich verstehe es als "hat dieselben Mitglieder". sameMembers([1,1,2],[2,1,2])sollte truemeiner Meinung nach zurückkehren. sameMembersInOrder([1,1,2],[2,1,2])AKA deepEquals([1,1,2],[2,1,2])sollte zurückkehren false.
Max Heiber
Ihre dritte Lösung arr1.filter...funktioniert nur, um zu überprüfen, ob arr2 alle Elemente von arr1 enthält oder nicht, aber nicht umgekehrt, was ebenfalls erforderlich ist.
Aakash Verma
9

Objektgleichheitsprüfung:JSON.stringify(array1.sort()) === JSON.stringify(array2.sort())

Der obige Test funktioniert auch mit Arrays von Objekten. In diesem Fall wird eine Sortierfunktion verwendet, die unter http://www.w3schools.com/jsref/jsref_sort.asp dokumentiert ist

Könnte für kleine Arrays mit flachen JSON-Schemas ausreichen.

Sandeep
quelle
9

Unser Ziel ist es grundsätzlich zu überprüfen, ob 2 Arrays gleiche Mengen sind. set ist die mathematisch definierte Menge . Die schnellste asymptotische Sortierung benötigt O (nlog (n)) Zeit. Wenn Sie also ein Array sortieren, dauert es mindestens O (nlog (n)) . Sie können diese Aufgabe jedoch schneller erledigen , was bei einer Wörterbuchdatenstruktur asymptotisch O (n) Zeit in Anspruch nimmt (Durchschnittsfall nicht Worst Case). In JS ist ein Wörterbuch einfach ein Objekt mit Schlüsseln und Werten.

/** assumes array elements are primitive types
* check whether 2 arrays are equal sets.
* @param  {} a1 is an array
* @param  {} a2 is an array
*/
function areArraysEqualSets(a1, a2) {
  const superSet = {};
  for (const i of a1) {
    const e = i + typeof i;
    superSet[e] = 1;
  }

  for (const i of a2) {
    const e = i + typeof i;
    if (!superSet[e]) {
      return false;
    }
    superSet[e] = 2;
  }

  for (let e in superSet) {
    if (superSet[e] === 1) {
      return false;
    }
  }

  return true;
}

Beachten Sie, dass diese Funktion mit Arrays primitiver Typen funktioniert a1und a2Arrays annimmt und sind.

canbax
quelle
5

Was ist damit? ES 2017 nehme ich an:

const array1 = [1, 3, 5];
const array2 = [1, 5, 3];

const isEqual = (array1.length === array2.length) && (array1.every(val => array2.includes(val)));
console.log(isEqual);

Die erste Bedingung prüft, ob beide Arrays dieselbe Länge haben, und die zweite Bedingung prüft, ob das erste Array eine Teilmenge des zweiten Arrays ist. Die Kombination dieser beiden Bedingungen sollte dann zu einem Vergleich aller Elemente der beiden Arrays führen, unabhängig von der Reihenfolge der Elemente.

Der obige Code funktioniert nur, wenn beide Arrays nicht doppelte Elemente enthalten.

Ramandeep Singh
quelle
3

Wenn Sie diese beiden Arrays vergleichen, vergleichen Sie die Objekte, die die Arrays darstellen, nicht den Inhalt.

Sie müssen eine Funktion verwenden, um die beiden zu vergleichen. Sie können Ihre eigene schreiben, die einfach eine Schleife durchläuft und diese mit der anderen vergleicht, nachdem Sie überprüft haben, ob die Längen gleich sind.

Andrew
quelle
3

Einfache Lösung für flache Gleichstellung mit ES6:

const arr1test = arr1.slice().sort()
const arr2test = arr2.slice().sort()
const equal = !arr1test.some((val, idx) => val !== arr2test[idx])

Erstellt flache Kopien jedes Arrays und sortiert sie. Verwendet dann some()eine Schleife durch arr1testWerte und vergleicht jeden Wert mit dem Wert in arr2testmit demselben Index. Sind alle Werte gleich sind, some()kehrt false, und wiederum equalausgewertet true.

Könnte auch verwendet werden every(), müsste aber jedes Element im Array durchlaufen, um ein trueErgebnis zu erzielen , während some()es sich retten wird, sobald es einen Wert findet, der nicht gleich ist:

const equal = arr1test.every((val, idx) => val === arr2test[idx])
Camslice
quelle
2

Ich hatte einfache ganzzahlige Werte in einem Spielprojekt.
Hatte weniger Werte in jedem Array. Außerdem brauchte
ich das ursprüngliche Array unberührt. Also habe ich das Folgende getan, es hat gut funktioniert. (Code bearbeitet, um hier einzufügen)

var sourceArray = [1, 2, 3];
var targetArray = [3, 2, 1];

if (sourceArray.length !== targetArray.length) {
    // not equal
    // did something
    return false;
}

var newSortedSourceArray = sourceArray.slice().sort();
var newSortedTargetArray = targetArray.slice().sort();

if (newSortedSourceArray.toString() !== newSortedTargetArray.toString()) { // MAIN CHECK
    // not equal
    // did something
    return false;
}
else {
    // equal
    // did something
    // continued further below
}

// did some more work

return true;

Hoffentlich hilft das.

Manohar Reddy Poreddy
quelle
2

Verwenden von ES6

Wir werden Ramdas equalsFunktion verwenden, aber stattdessen können wir die von Lodash oder Underscore verwenden isEqual:

const R = require('ramda');

const arraysHaveSameValues = (arr1, arr2) => R.equals( [...arr1].sort(), [...arr2].sort() )

Mit dem Spread-Opporator vermeiden wir die Mutation der ursprünglichen Arrays und halten unsere Funktion rein.

Ben Carp
quelle
2

Sie können reduceanstelle von Loops verwenden, um clever zu wirken, aber auf die Gefahr hin, dass Ihre Kollegen Sie als Smart-Ass betrachten.

function isArrayContentSame(a, b) {
  if (Array.isArray(a) && Array.isArray(b) && a.length == b.length) {
    a = a.concat().sort()
    b = b.concat().sort()
    return a.reduce((acc,e,i) => acc && e === b[i], true)
  } else {
    return false;
  }
}
Bemmu
quelle
1

Wenn die Elemente im Array Grundelemente (Zahlen oder einzelne Zeichen) sind, können Sie eine Kombination aus Längenvergleich und Verwendung von Mengen verwenden.

function equalArrayItems(arr1, arr2) {
  if (arr1.length !== arr2.length) return false
  const set1 = new Set(arr1)
  const set2 = new Set(arr2)
  const set3 = new Set(arr1, arr2)
  return set1.size === set3.size && set2.size === set3.size
}
Stefan Musarra
quelle
1

Es ist bereits 2020, aber ich habe festgestellt, dass die meisten anderen Lösungen sort, O (n * log n), Bibliotheken oder O (n ^ 2) -Komplexität verwenden.

Hier ist eine reine Javascript-Lösung mit linearer Komplexität, O (n):

/**
 * Check if two arrays of strings or numbers have the same values regardless of the order
 * @param {string[]|number[]} arr1
 * @param {string[]|number[]} arr2
 * @return {boolean}
 */    
compareArrays = (arr1, arr2) => {
    if (arr1.length !== arr2.length) return false;
    const lk1 = {};
    const lk2 = {};
    let i = arr1.length;
    while (--i >= 0) {
        lk1[arr1[i]] = true;
        lk2[arr2[i]] = true
    }
    i = arr1.length;
    while (--i >= 0) {
        const v = arr1[i];
        if (lk1[v] !== lk2[v]) return false;
    }
    return true
}

Tests:

compareArrays([2, 4], [4, 2]) => true
compareArrays([2, 4], [4, 2, 7]) => false
compareArrays([], []) => true
SC1000
quelle
Hey, das ist ein großartiger Eintrag! Es ist ziemlich verworren, aber es macht Sinn. Ich habe eine Frage: Ich bin mit der Big O-Notation nicht sehr vertraut, aber dieser Algorithmus ist sicherlich O (2n)? Denken Sie jedoch nicht, dass dies einen großen Unterschied macht.
Carlos Precioso vor
1
@CarlosPrecioso Das ist richtig und O (2n) = O (n). Die Komplexität ändert sich nicht durch Multiplikation mit einem konstanten Faktor
SC1000 vor
0

Wenn Sie das Prototype Framework verwenden, können Sie die intersect- Methode eines Arrays verwenden, um herauszufinden, ob sie identisch sind (unabhängig von der Reihenfolge):

var array1 = [1,2];
var array2 = [2,1];

if(array1.intersect(array2).length === array1.length) {
    alert("arrays are the same!");
}
Erfan
quelle
Dies funktioniert nicht - [1,2].intersect([1,2,3]).length === [1,2].lengthgibt true zurück. Sie sollten auch die Länge der ursprünglichen Arrays vergleichen. Ich habe den Beitrag bearbeitet, um dies zu demonstrieren.
GMA
Eigentlich habe ich gerade festgestellt, dass meine vorgeschlagene Bearbeitung bei Duplikaten nicht funktioniert ... z. B. wird sie falsch zurückgeben für array1 = [1,1,2]; array2 = [1,1,2];... die ursprüngliche Antwort schlägt für diese Eingabe nicht fehl.
GMA
Sie können das Gegenteil mit_.difference(array1, array2).length;
Vic
0

Bitte überprüfen Sie diese Antwort

var arr1= [12,18];
var arr2= [12, 18, 20, 11, 19, 14, 6, 7, 8, 16, 9, 3, 1, 13, 5, 4, 15, 10, 2, 17];
for(i=0;i<arr1.length;i++)
{
var array1=arr1[i];
for(j=0;j<arr2.length;j++)
{
    var array2=arr2[j];
    if(array1==array2)
    {
return true;
    }
}
}
Vinoth
quelle
2
Dies entspricht funktional dieser Antwort , abgesehen von einigen Fehlern. Erstens sollte dies alles in eine Funktion eingeschlossen sein, returnsonst hat dies keine Auswirkung. Zweitens sollten Sie die sortierten Arrays überprüfen, wie [1,2]und [2,1]wird als nicht derselben erkannt werden. Drittens und vor allem wird dabei nur geprüft, ob ein Element dasselbe ist. Die Bedingung sollte sein if (array1!==array2) {return false;}. Vielleicht kann Ihnen das in Zukunft helfen!
Carlos Precioso
1
Versuchen Sie als zusätzlichen Kommentar, Einrückungen zum besseren Verständnis des Codeflusses sowie klarere Variablennamen zu verwenden. ZB: array1und array2könnte umbenannt werden elem1und elem2. Beide Tipps ersparen Ihnen in Zukunft viele Kopfschmerzen!
Carlos Precioso
2
Warum bei weiterer Betrachtung die Doppelschleife? Beide Arrays sollten gleich lang sein, und wenn nicht, sind sie direkt nicht gleich. Auf diese Weise können Sie nur eine Schleife verwenden. Gerade jetzt, dieser Code überprüft , ob jede der Elemente des ersten Arrays sind überall in der zweiten. Überprüfen Sie diese Antwort, um zu sehen, wie Sie sie implementieren sollten. Viel Glück bei Ihrer JavaScript-Reise!
Carlos Precioso
0

Antworten Sie nach langer Zeit, aber hoffen Sie, dass dies jemandem hilft, der nach einer einfachen Lösung und modernen Neulingen sucht.

Jetzt können wir diese mit mehreren Bibliotheken wie erreichen lodash, underscoreetc. (dieser Teil des Projektes heute aufgrund der Einfachheit, mehr Funktionen und hoher Nutzung wird)

Sie können die Kreuzung aus der Lodash-Bibliothek verwenden.

_.intersection(['2-1', '1'], ['2-2', '3-1', '2-1']); 
// => ['2-1']

Dies funktioniert für jeden Datentyp.

Prasanth Jaya
quelle
0

Wenn Sie zwei Arrays vergleichen und prüfen möchten, ob ein Objekt in beiden Arrays identisch ist, funktioniert dies. Beispiel:

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

Hier ist 'd' in beiden Arrays gleich, sodass diese Funktion den wahren Wert zurückgibt.

  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;
  }
Sandip Moradiya
quelle
0

Versuche dies

function arraysEqual(arr1, arr2){
    if (!Array.isArray(arr1) || !Array.isArray(arr2) || arr1.length!=arr2.length)
        return false;

    return arr1.length==arr1.filter(word => arr2.includes(word)).length;
}
Dimitrios Stefos
quelle
0

Ich habe einen anderen Weg basierend auf der akzeptierten Antwort.

function compareArrays(array1, array2) {

    if (
        !Array.isArray(array1)
        || !Array.isArray(array2)
        || array1.length !== array2.length
    ) return false;

    var first = array1.sort().map(value => (String(value))).join();
    var second = array2.sort().map(value => (String(value))).join();

    return first == second ? true : false;
}
Cristopher Paniagua
quelle
Hey, willkommen bei StackOverflow! Während diese Antwort in einigen Fällen funktionieren würde, würde es einige spezielle Fälle geben, in denen dies nicht der Fall wäre. Beachten Sie zunächst, dass .sort () das ursprüngliche Array ändert. Heutzutage wird dies als schlechte Hygiene angesehen. Deshalb führt die ursprüngliche Antwort zuerst eine .concat () aus, um eine Kopie zu erstellen.
Carlos Precioso
Und zweitens würde dies nicht konsistent mit dem Rest von JavaScript funktionieren. {foo: "bar"} === {foo: "bar"} gibt false zurück (es handelt sich um zwei verschiedene Objekte, die separat erstellt wurden); Daher sollten compareArrays ([{foo: "bar"}], [{foo: "bar"}]) aus Konsistenzgründen auch false zurückgeben. Bei Ihrer Implementierung wird jedoch true zurückgegeben, da die Zeichenfolgendarstellung der Objekte identisch ist. Das könnte ein gewünschtes Verhalten sein oder nicht, aber eines, auf das man auf jeden Fall achten sollte.
Carlos Precioso
0

Eine Funktion zum Vergleichen von zwei Arrays, um zu überprüfen, ob beide dieselben Elemente haben. Auch wenn sie nicht in Ordnung sind ...

Es ist gut für einfache Arrays. [String, Number, Boolean, null, NaN].

Ich verwende nicht .sort (), es ändert das ursprüngliche Array. Einige sagen, es ist schlecht ...

Vorsicht. Diese Funktion ist eingeschränkt und kann keine Objekte "[], {}" oder Funktionen in diesen Arrays vergleichen. Arrays selbst sind Objekte.

   let arraysHasSameElements = (arr1, arr2) => {
        let count =
            // returns counting of occurrences.
            (arr, val) => arr.reduce((count, curr) => (curr === val ? 1 : 0) + count, 0);

        /* this will return true if lengths of the arrays is equal.
           then compare them.*/
        return arr1.length === arr2.length

            // compare arr1 against arr2.
            && arr1.reduce((checks, val) =>

                /*  creating array of checking if a value has equal amount of occurrences
                    in both arrays, then adds true 'check'. */
                checks.concat(count(arr1, val) === count(arr2, val)), [])

                // checking if each check is equal to true, then .every() returns true.
                .every(check => check);
    }

    let arr1 = ['',-99,true,NaN,21,null,false,'help',-99,'help',NaN], 
        arr2 = [null,-99,'',NaN,NaN,false,true,-99,'help',21,'help'];
    arraysHasSameElements(arr1, arr2); //true

    let arr3 = [false,false,false,false,false,false], 
        arr4 = [false,false,false,false,false,false]
    arraysHasSameElements(arr3, arr4); //true


    // here we have uncommented version.
    let arraysHasSameElements = (arr1, arr2) => {
        let count = (arr, val) => arr.reduce((count, curr) => (curr === val ? 1:0) + count, 0);
        return arr1.length === arr2.length && arr1.reduce((checks, val) =>
            checks.concat(count(arr1, val) === count(arr2, val)), []).every(check => check);
    }
Magnus Fohlström
quelle
-1

Einfache Lösung zum Vergleichen der beiden Arrays:

var array1 = [2, 4];
var array2 = [4, 2];

array1.sort();
array2.sort();

if (array1[0] == array2[0]) {
    console.log("Success");
}else{
    console.log("Wrong");
}
Luqman Shofuleji
quelle