Ich habe eine Reihe von Zahlen, die ich sicherstellen muss, dass sie eindeutig sind. Ich habe das Code-Snippet unten im Internet gefunden und es funktioniert großartig, bis das Array eine Null enthält. Ich habe dieses andere Skript gefunden hier auf Stack Overflow gefunden, das fast genau so aussieht, aber nicht fehlschlägt.
Kann mir jemand helfen, festzustellen, wo das Prototyp-Skript falsch läuft, um mir beim Lernen zu helfen?
Array.prototype.getUnique = function() {
var o = {}, a = [], i, e;
for (i = 0; e = this[i]; i++) {o[e] = 1};
for (e in o) {a.push (e)};
return a;
}
Weitere Antworten von doppelten Fragen:
Ähnliche Frage:
javascript
arrays
unique
Mottie
quelle
quelle
o
=object
,a
=array
,i
=index
unde
= umm, etwas: PAntworten:
Mit JavaScript 1.6 / ECMAScript 5 können Sie die native
filter
Methode eines Arrays folgendermaßen verwenden, um ein Array mit eindeutigen Werten abzurufen:Die native Methode
filter
durchläuft das Array und hinterlässt nur die Einträge, die die angegebene Rückruffunktion bestehenonlyUnique
.onlyUnique
prüft, ob der angegebene Wert der erste ist, der auftritt. Wenn nicht, muss es ein Duplikat sein und wird nicht kopiert.Diese Lösung funktioniert ohne zusätzliche Bibliothek wie jQuery oder prototype.js.
Es funktioniert auch für Arrays mit gemischten Werttypen.
Für alten Browser (<ie9), das nicht unterstützt die nativen Methoden
filter
undindexOf
Sie können Workarounds in der MDN - Dokumentation finden Filter und indexOf .Wenn Sie das letzte Vorkommen eines Werts beibehalten möchten, ersetzen Sie ihn einfach
indexOf
durchlastIndexOf
.Mit ES6 könnte dies verkürzt werden:
Vielen Dank an Camilo Martin für den Hinweis im Kommentar.
ES6 verfügt über ein natives Objekt
Set
zum Speichern eindeutiger Werte. Um ein Array mit eindeutigen Werten zu erhalten, können Sie jetzt Folgendes tun:Der Konstruktor von
Set
nimmt ein iterierbares Objekt wie Array, und der Spread-Operator...
wandelt die Menge wieder in ein Array um. Vielen Dank an Lukas Liese für den Hinweis im Kommentar.quelle
['a', 1, 'a', 2, '1']
würden Sie bekommen['a', 1, 2]
. Aber das habe ich nicht erwartet. Übrigens ist viel langsamer sehr relativ..filter((v,i,a)=>a.indexOf(v)==i)
(fette Pfeilnotation).let unique_values = [...new Set(random_array)];
developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…Aktualisierte Antwort für ES6 / ES2015 : Mit dem Set lautet die einzeilige Lösung:
Welches kehrt zurück
Wie von le_m vorgeschlagen, kann dies auch mit dem Spread-Operator wie z
quelle
Array.from(new Set([[1,2],[1,2],[1,2,3]]))
myArray.filter((v, i, a) => a.indexOf(v) === i);
?Set
Objekte und anstelle von primitiven Werten hinzufügen, eindeutige Verweise auf die Objekte enthalten. Das Set-s
In gibt alsolet s = new Set([{Foo:"Bar"}, {Foo:"Bar"}]);
Folgendes zurück: DiesSet { { Foo: 'Bar' }, { Foo: 'Bar' } }
ist einSet
mit eindeutigen Objektverweisen auf Objekte, die dieselben Werte enthalten. Wenn Sie schreibenlet o = {Foo:"Bar"};
und dann ein Set mit zwei Referenzen wielet s2 = new Set([o,o]);
folgt erstellen : dann wird s2Set { { Foo: 'Bar' } }
new Set
's TrophäeMir ist klar, dass diese Frage bereits mehr als 30 Antworten hat. Aber ich habe zuerst alle vorhandenen Antworten durchgelesen und meine eigenen Nachforschungen angestellt.
Ich habe alle Antworten auf 4 mögliche Lösungen aufgeteilt:
[...new Set( [1, 1, 2] )];
{ }
, um Duplikate zu vermeiden[ ]
filter + indexOf
Hier sind Beispielcodes in den Antworten:
Verwenden Sie die neue ES6-Funktion:
[...new Set( [1, 1, 2] )];
Verwenden Sie Objekt
{ }
, um Duplikate zu vermeidenVerwenden Sie das Helper-Array
[ ]
Verwenden
filter + indexOf
Und ich habe mich gefragt, welches schneller ist. Ich habe ein Beispiel für Google Sheet erstellt , um Funktionen zu testen. Hinweis: ECMA 6 ist in Google Sheets nicht verfügbar, daher kann ich es nicht testen.
Hier ist das Ergebnis von Tests:
Ich habe erwartet, dass Code mit Objekt
{ }
gewinnt, weil er Hash verwendet. Daher bin ich froh, dass Tests die besten Ergebnisse für diesen Algorithmus in Chrome und IE gezeigt haben. Danke an @rab für den Code .quelle
Sie können auch underscore.js verwenden .
welches zurückkehren wird:
quelle
array = [...new Set(array)]
Ein Liner, reines JavaScript
Mit ES6-Syntax
list = list.filter((x, i, a) => a.indexOf(x) == i)
Mit ES5-Syntax
Browserkompatibilität : IE9 +
quelle
Ich habe seitdem eine nette Methode gefunden, die jQuery verwendet
Hinweis: Dieser Code wurde aus Paul Irishs Entenstanzpfosten gezogen - ich habe vergessen, eine Gutschrift zu geben: P.
quelle
Kürzeste Lösung mit ES6:
[...new Set( [1, 1, 2] )];
Oder wenn Sie den Array-Prototyp ändern möchten (wie in der ursprünglichen Frage):
EcmaScript 6 ist derzeit (August 2015) nur teilweise in modernen Browsern implementiert , Babel jedoch ist sehr beliebt geworden, um ES6 (und sogar ES7) zurück auf ES5 zu übertragen. Auf diese Weise können Sie heute ES6-Code schreiben!
Wenn Sie sich fragen, was das
...
bedeutet, wird es als Spread-Operator bezeichnet . Von MDN : «Mit dem Spread-Operator kann ein Ausdruck an Stellen erweitert werden, an denen mehrere Argumente (für Funktionsaufrufe) oder mehrere Elemente (für Array-Literale) erwartet werden». Da ein Set iterierbar ist (und nur eindeutige Werte haben kann), erweitert der Spread-Operator das Set, um das Array zu füllen.Ressourcen zum Lernen von ES6:
quelle
a = [...Set(a)]
aber dies ist vorerst nur Firefox.require ( "core-js/fn/array/from" );
[...Set(['a', 1, 'a', 2, '1'])]
wird einen TypeError werfen, daher ist es immer noch ratsam, Folgendes beizubehaltennew
:[...new Set(['a', 1, 'a', 2, '1'])]
Einfachste Lösung:
Oder:
quelle
Der einfachste und schnellste (in Chrome) Weg, dies zu tun:
Durchläuft einfach jedes Element im Array, testet, ob dieses Element bereits in der Liste enthalten ist, und drückt es auf das Array, das zurückgegeben wird, wenn dies nicht der Fall ist.
Laut jsPerf ist diese Funktion die schnellste, die ich jemals finden konnte - Sie können jedoch auch Ihre eigene hinzufügen.
Die Nicht-Prototyp-Version:
Sortierung
Wenn Sie das Array auch sortieren müssen, ist Folgendes am schnellsten:
oder Nicht-Prototyp:
Dies ist in den meisten Nicht-Chrome-Browsern auch schneller als die oben beschriebene Methode .
quelle
unique
Funktion implementiert haben, eine Komplexität von O (n ^ 2), während der ingetUnique
O (n) ist. Der erste mag bei kleinen Datenmengen schneller sein, aber wie können Sie mit der Mathematik argumentieren :) Sie können sicherstellen, dass der letztere schneller ist, wenn Sie ihn auf einer Reihe von beispielsweise 1e5 einzigartigen Elementen ausführenNUR LEISTUNG! Dieser Code ist wahrscheinlich 10x schneller als alle Codes hier * funktioniert in allen Browsern und hat auch die geringste Auswirkung auf den Speicher .... und mehr
Wenn Sie das alte Array nicht wiederverwenden müssen, müssen Sie übrigens die erforderlichen anderen Vorgänge ausführen, bevor Sie es in ein einzigartiges Array konvertieren. Dies ist wahrscheinlich der schnellste Weg, um dies zu tun, auch sehr kurz.
dann können Sie dies versuchen
Ich habe mir diese Funktion ausgedacht, als ich diesen Artikel gelesen habe ...
http://www.shamasis.net/2009/09/fast-algorithm-to-find-unique-items-in-javascript-array/
Ich mag die for-Schleife nicht. Es hat zu viele Parameter. Ich mag die while-- Schleife. while ist die schnellste Schleife in allen Browsern außer der, die wir alle so sehr mögen ... Chrome.
Trotzdem habe ich die erste Funktion geschrieben, die while verwendet. Und ja, sie ist etwas schneller als die im Artikel gefundene Funktion. Aber nicht genug.
unique2()
nächster schritt moderne js verwenden.
Object.keys
Ich habe die andere for-Schleife durch die Object.keys von js1.7 ersetzt ... etwas schneller und kürzer (in Chrome 2x schneller);). Nicht genug!.unique3()
.Zu diesem Zeitpunkt dachte ich darüber nach, was ich wirklich in MEINER einzigartigen Funktion brauche. Ich brauche das alte Array nicht, ich möchte eine schnelle Funktion. Also habe ich 2 while-Schleifen + Spleißen verwendet.
unique4()
Es ist nutzlos zu sagen, dass ich beeindruckt war.
Chrom: Die üblichen 150.000 Operationen pro Sekunde stiegen auf 1.800.000 Operationen pro Sekunde.
dh: 80.000 op / s gegenüber 3.500.000 op / s
ios: 18.000 op / s vs 170.000 op / s
Safari: 80.000 op / s vs 6.000.000 op / s
Beweis http://jsperf.com/wgu oder besser console.time ... microtime ... was auch immer verwenden
unique5()
soll Ihnen nur zeigen, was passiert, wenn Sie das alte Array behalten möchten.Verwenden Sie nicht,
Array.prototype
wenn Sie nicht wissen, was Sie tun. Ich habe gerade viel kopiert und vergangen. VerwendenObject.defineProperty(Array.prototype,...,writable:false,enumerable:false})
Sie diese Option, wenn Sie einen nativen Prototyp erstellen möchten. Beispiel: https://stackoverflow.com/a/20463021/2450730Demo http://jsfiddle.net/46S7g/
HINWEIS: Ihr altes Array wird nach diesem Vorgang zerstört / wird einzigartig.
Wenn Sie den obigen Code nicht lesen können, lesen Sie ein Javascript-Buch oder hier finden Sie einige Erklärungen zu kürzerem Code. https://stackoverflow.com/a/21353032/2450730
Einige verwenden
indexOf
... nicht ... http://jsperf.com/dgfgghfghfghghgfhgfhfghfhgfhfür leere Arrays
quelle
Viele der Antworten hier sind für Anfänger möglicherweise nicht hilfreich. Wenn es schwierig ist, ein Array zu de-dupen, wissen sie dann wirklich etwas über die Prototypenkette oder sogar über jQuery?
In modernen Browsern besteht eine saubere und einfache Lösung darin, Daten in einem Set zu speichern , das als Liste eindeutiger Werte konzipiert ist.
Dies
Array.from
ist nützlich, um das Set wieder in ein Array zu konvertieren, damit Sie einfachen Zugriff auf alle fantastischen Methoden (Funktionen) von Arrays haben. Es gibt auch andere Möglichkeiten , dasselbe zu tun. Möglicherweise benötigen Sie dies jedoch überhaupt nichtArray.from
, da Sets zahlreiche nützliche Funktionen wie forEach enthalten .Wenn Sie den alten Internet Explorer unterstützen müssen und Set daher nicht verwenden können, besteht eine einfache Methode darin, Elemente in ein neues Array zu kopieren, während Sie zuvor prüfen, ob sie sich bereits im neuen Array befinden.
Um dies sofort wiederverwendbar zu machen, fügen wir es in eine Funktion ein.
Um die Duplikate loszuwerden, würden wir dies jetzt tun.
Der
deduplicate(cars)
Teil wird zu dem, was wir als Ergebnis bezeichnet haben das wenn die Funktion abgeschlossen ist.Übergeben Sie einfach den Namen eines beliebigen Arrays.
quelle
quelle
push
das Element nicht einfach auf das Array gesetzt haben, anstatt es zu verwendenconcat
? Ich habe versucht, Push zu verwenden, und es ist fehlgeschlagen. Ich suche eine Erklärung.[0,1,2,0,3,2,1,5].reduce((prev, cur) => ~prev.indexOf(cur) ? prev : prev.concat([cur]), []);
NaN
freundlichWir können dies mit ES6-Sets tun:
// Die Ausgabe wird sein
quelle
Dieser Prototyp
getUnique
ist nicht ganz korrekt, denn wenn ich ein Array wie das folgende habe:["1",1,2,3,4,1,"foo"]
Es wird zurückgegeben["1","2","3","4"]
und"1"
ist ein String und1
eine Ganzzahl. Sie sind anders.Hier ist eine richtige Lösung:
mit:
Das obige wird produzieren
["1",2,3,4,1,"foo"]
.quelle
$foo = 'bar'
die PHP-Methode zum Deklarieren von Variablen ist. Es funktioniert in Javascript, erstellt jedoch ein implizites globales Element und sollte im Allgemeinen nicht durchgeführt werden.$foo
ist die Art und Weise, Variablen in Javascript zu deklarieren, während dies tatsächlich der Fallvar foo
ist.Ohne Array.prototype zu erweitern (es wird als schlechte Praxis bezeichnet) oder jquery / underscore zu verwenden, können Sie
filter
das Array einfach erweitern .Durch Beibehalten des letzten Auftretens:
oder erstes Auftreten:
Nun, es ist nur Javascript ECMAScript 5+, was nur IE9 + bedeutet, aber es ist gut für eine Entwicklung in nativem HTML / JS (Windows Store App, Firefox OS, Sencha, Phonegap, Titan, ...).
quelle
filter
. Auf der MDN-Seite haben sie eine Implementierung für Internet Explorer, ich meine ältere Browser. Außerdem: JS 1.6 bezieht sich nur auf die js-Engine von Firefox, aber das Richtige ist, dass es sich um ECMAScript 5 handelt.Magie
O (n) Leistung ; Wir gehen davon aus, dass sich Ihr Array in
a
und befindett={}
. Erklärung hier (+ Jeppe Impr.)Code-Snippet anzeigen
quelle
in
Operator außerhalb der anderen Konstruktion alsfor
Schleife verwenden kann: P) - Danke - ich weiß das zu schätzen und werde Ihren anderen guten Antworten +2 geben .t
, die nach dem Filtern am Leben bleibt?quelle
Wenn Sie das Prototype-Framework verwenden, müssen keine 'for'-Schleifen ausgeführt werden. Sie können http://www.prototypejs.org/api/array/uniq folgendermaßen verwenden :
Dadurch wird ein doppeltes Array ohne Duplikate erstellt. Ich bin auf Ihre Frage gestoßen, als ich nach einer Methode gesucht habe, um verschiedene Array-Datensätze zu zählen
ich benutzte
und da war mein einfaches Ergebnis. ps Entschuldigung, wenn ich etwas falsch geschrieben habe
Bearbeiten: Wenn Sie undefinierte Datensätze maskieren möchten, möchten Sie diese möglicherweise hinzufügen
vorher so:
quelle
Mit Sets können Sie jetzt Duplikate entfernen und wieder in das Array konvertieren.
Eine andere Lösung ist die Verwendung von Sortieren und Filtern
quelle
Das
0
liegt daran, dass es sich bei JavaScript um einen falschen Wert handelt.this[i]
wird falsch sein, wenn der Wert des Arrays 0 oder ein anderer falscher Wert ist.quelle
quelle
o
statt nur in a gespeichert wird1
, obwohl der Gleichheitsvergleich immer noch stringweise wäre (obwohl er von allen möglichen Javascript-Gleichheiten nicht allzu unvernünftig erscheint).Ich hatte ein etwas anderes Problem, bei dem ich Objekte mit doppelten ID-Eigenschaften aus einem Array entfernen musste. das hat funktioniert.
quelle
Die einfachste Antwort lautet:
quelle
Ich bin mir nicht sicher, warum Gabriel Silveira die Funktion so geschrieben hat, aber eine einfachere Form, die für mich genauso gut und ohne Minimierung funktioniert, ist:
oder in CoffeeScript:
quelle
Wenn Sie mit zusätzlichen Abhängigkeiten einverstanden sind oder bereits eine der Bibliotheken in Ihrer Codebasis haben, können Sie mit LoDash (oder Underscore) Duplikate aus einem vorhandenen Array entfernen.
Verwendungszweck
Wenn Sie es noch nicht in Ihrer Codebasis haben, installieren Sie es mit npm:
Verwenden Sie es dann wie folgt:
Aus:
quelle
Dies wurde viel beantwortet, aber es wurde nicht auf meine besonderen Bedürfnisse eingegangen.
Viele Antworten lauten wie folgt:
Dies funktioniert jedoch nicht für Arrays komplexer Objekte.
Angenommen, wir haben ein Array wie dieses:
Wenn wir die Objekte mit eindeutigen Namen haben möchten, sollten wir
array.prototype.findIndex
anstelle vonarray.prototype.indexOf
:quelle
Aus Shamasis Bhattacharyas Blog (O (2n) Zeitkomplexität):
Aus Paul Irishs Blog : Verbesserung von JQuery
.unique()
:quelle
Finden eindeutiger Array-Werte in einer einfachen Methode
quelle
Es scheint, dass wir Rafaels Antwort verloren haben , die einige Jahre lang als akzeptierte Antwort galt. Dies war (zumindest 2017) die leistungsstärkste Lösung, wenn Sie kein Array vom gemischten Typ haben :
Wenn Sie tun , ein Array Mischtyp haben, können Sie die Raute - Taste serialisiert:
quelle
Um das Problem umgekehrt zu lösen, kann es nützlich sein, beim Laden Ihres Arrays kein Duplikat zu haben, so wie es das Set- Objekt tun würde, aber es ist noch nicht in allen Browsern verfügbar. Es spart Speicher und ist effizienter, wenn Sie den Inhalt mehrmals betrachten müssen.
Stichprobe:
Gibt Ihnen
set = [1,3,4,2]
quelle