Wie überprüfe ich in Javascript, ob ein Array doppelte Werte enthält?

91

Mögliches Duplikat:
einfachste Weg, doppelte Werte in einem Javascript-Array zu finden

Wie überprüfe ich, ob ein Array doppelte Werte hat?

Wenn einige Elemente im Array identisch sind, geben Sie true zurück. Andernfalls geben Sie false zurück.

['hello','goodbye','hey'] //return false because no duplicates exist
['hello','goodbye','hello'] // return true because duplicates exist

Beachten Sie, dass es mir egal ist, die Duplizierung zu finden. Ich möchte nur ein boolesches Ergebnis, wenn Arrays Duplikate enthalten.

user847495
quelle
Hier ist es: stackoverflow.com/questions/840781/…
Ofer Zelig
2
Ich möchte nicht, dass eine Liste von Duplikaten entfernt wird. Ich möchte nur wissen, ob wahr oder falsch ist, wenn eine Liste Duplikate enthält.
user847495
7
Diese Frage ist kein Duplikat. Da @ user847495 lediglich überprüfen möchte, ob Duplikate vorhanden sind, ist die Lösung schneller / einfacher als erforderlich, um alle Vorkommen von Duplikaten zu finden. Zum Beispiel können Sie dies tun: codr.io/v/bvzxhqm
alden
2
mit Unterstrich , einfache Technikvar test=['hello','goodbye','hello'] ; if ( test.length != _.unique(test).length ) { // some code }
Sai Ram
4
Kein Duplikat der markierten Frage. Bitte achten Sie darauf, bevor Sie Fragen als solche markieren.
John Weisz

Antworten:

209

Wenn Sie eine ES2015-Umgebung haben (zum jetzigen Zeitpunkt: io.js, IE11, Chrome, Firefox, WebKit pro Nacht), funktioniert Folgendes und ist schnell (nämlich O (n)):

function hasDuplicates(array) {
    return (new Set(array)).size !== array.length;
}

Wenn Sie nur Zeichenfolgenwerte im Array benötigen, funktioniert Folgendes:

function hasDuplicates(array) {
    var valuesSoFar = Object.create(null);
    for (var i = 0; i < array.length; ++i) {
        var value = array[i];
        if (value in valuesSoFar) {
            return true;
        }
        valuesSoFar[value] = true;
    }
    return false;
}

Wir verwenden eine "Hash-Tabelle", valuesSoFarderen Schlüssel die Werte sind, die wir bisher im Array gesehen haben. Wir führen eine Suche durch in, um festzustellen , ob dieser Wert bereits erkannt wurde. Wenn ja, verlassen wir die Schleife und kehren zurück true.


Wenn Sie eine Funktion benötigen, die nicht nur für Zeichenfolgenwerte funktioniert, funktioniert Folgendes, ist jedoch nicht so performant. es ist O (n 2 ) anstelle von O (n).

function hasDuplicates(array) {
    var valuesSoFar = [];
    for (var i = 0; i < array.length; ++i) {
        var value = array[i];
        if (valuesSoFar.indexOf(value) !== -1) {
            return true;
        }
        valuesSoFar.push(value);
    }
    return false;
}

Der Unterschied besteht einfach darin, dass wir ein Array anstelle einer Hash-Tabelle für verwenden valuesSoFar, da JavaScript- "Hash-Tabellen" (dh Objekte) nur Zeichenfolgenschlüssel haben. Dies bedeutet, dass wir die O (1) -Suchzeit von verlieren inund stattdessen eine O (n) -Nachschlagzeit von erhalten indexOf.

Domenic
quelle
2
Über das erste Beispiel, das Sie gegeben haben. Ist die Validierung nicht genau umgekehrt? Wenn Ihre Funktion benannt ist hasDuplicates, sollte sie prüfen, ob die Größe des Sets während des Castings tatsächlich geschrumpft ist, oder? Daher sollte der boolesche Operator sein !==und nicht===
Tim Daubenschütz
Bitte bearbeiten. Ich kann nicht bearbeiten, da ich nicht mehr als 6 Zeichen ändere.
Tim Daubenschütz
1
Laut MDN unterstützt IE11 den im ersten Beispiel verwendeten Konstruktor nicht
adam77
Normale JS-Version gibt truefür das folgende Array zurück:[1, '1']
Kunal
Also "wenn Sie nur Zeichenfolgenwerte im Array benötigen" vor der Antwort.
Domenic
4

Ein anderer Ansatz (auch für Objekt- / Array-Elemente innerhalb des Arrays 1 ) könnte 2 sein :

function chkDuplicates(arr,justCheck){
  var len = arr.length, tmp = {}, arrtmp = arr.slice(), dupes = [];
  arrtmp.sort();
  while(len--){
   var val = arrtmp[len];
   if (/nul|nan|infini/i.test(String(val))){
     val = String(val);
    }
    if (tmp[JSON.stringify(val)]){
       if (justCheck) {return true;}
       dupes.push(val);
    }
    tmp[JSON.stringify(val)] = true;
  }
  return justCheck ? false : dupes.length ? dupes : null;
}
//usages
chkDuplicates([1,2,3,4,5],true);                           //=> false
chkDuplicates([1,2,3,4,5,9,10,5,1,2],true);                //=> true
chkDuplicates([{a:1,b:2},1,2,3,4,{a:1,b:2},[1,2,3]],true); //=> true
chkDuplicates([null,1,2,3,4,{a:1,b:2},NaN],true);          //=> false
chkDuplicates([1,2,3,4,5,1,2]);                            //=> [1,2]
chkDuplicates([1,2,3,4,5]);                                //=> null

Siehe auch...

1 benötigt einen Browser, der JSON unterstützt, oder eine JSON-Bibliothek, wenn nicht.
2 edit: Die Funktion kann jetzt zur einfachen Überprüfung oder zur Rückgabe eines Arrays doppelter Werte verwendet werden

KooiInc
quelle
3
Nicht-Showstopper-Probleme, die Sie beachten sollten: 1) Mutiert das zu sortierende Original-Array; 2) unterscheidet nicht zwischen null, NaN, Infinity, +Infinity, und -Infinity; 3) Objekte gelten als gleich, wenn sie dieselben eigenen Eigenschaften haben, auch wenn sie unterschiedliche Prototypen haben.
Domenic
1
@Domenic: Ja, hätte es erwähnen sollen. Bearbeitet, um die Mutation des ursprünglichen Arrays zu umgehen.
KooiInc
@Domenic: korrigiert um null / NaN / [+/-] Unendlich, siehe Änderungen.
KooiInc
@Domenic: Problem 3) ist eigentlich kein Problem für mich, weil es genau das ist, was ich will. Der Prototyp ist mir egal, nur die Werte.
Ehrfurcht