So erhalten Sie eindeutige Werte in einem Array [duplicate]
Lesezeit: 8 Minuten
Astronaut
Wie kann ich eine Liste mit eindeutigen Werten in einem Array erhalten? Muss ich immer ein zweites Array verwenden oder gibt es in JavaScript etwas Ähnliches wie die Hashmap von Java?
Ich werde verwenden JavaScript und jQuery nur. Es können keine zusätzlichen Bibliotheken verwendet werden.
stackoverflow.com/questions/5381621/… – beschreibt genau das, was Sie wollen, denke ich?
– SpaceBison
28. Juni 2012 um 14:24 Uhr
Sind Sie offen für die Verwendung der underscore.js Bücherei?
– jakee
28. Juni 2012 um 14:29 Uhr
Eine Java-Hashmap ist im Grunde dasselbe wie ein Javascript-Objekt. Syntax ist {“Schlüssel”: “Wert”, “Schlüssel2”: “Wert2”}
– Jan
28. Juni 2012 um 14:29 Uhr
JavaScript/TypeScript-Sammlungs-APIs sind im Vergleich zu Scala schrecklich, list.toSet
– Jordan Stewart
12. Dezember 2019 um 2:36 Uhr
Es hängt davon ab, was sich im Array befindet, wie Sie “Eindeutigkeit” definieren und wie groß Ihre Daten sind. Wenn es sich um Objekte handelt, unterscheidet sich der Code von Zahlen oder Zeichenfolgen, und wenn die Daten sehr groß sind, möchten Sie eher eine lineare als eine quadratische Lösung. Bitte geben Sie weitere Details an.
– ggorlen
15. September 2020 um 15:22 Uhr
Charles Clayton
Hier ist eine viel sauberere Lösung für ES6, die meiner Meinung nach hier nicht enthalten ist. Es verwendet die Satz und das Spread-Operator: ...
var a = [1, 1, 2];
[... new Set(a)]
Was zurückkehrt [1, 2]
Das ist so clever!
– Josh Mc
6. April 2017 um 22:40 Uhr
Jetzt, DAS ist ein Einzeiler!
– Mac
8. Dezember 2017 um 20:21 Uhr
In Typescript müssen Sie verwenden Array.from(new Set(a)) da Set nicht implizit in einen Array-Typ konvertiert werden kann. Nur ein Kopf hoch!
– Zachscs
27. April 2018 um 21:25 Uhr
Das ist großartig, aber achten Sie auf die Leistung, wenn Sie mit einer ziemlich großen Liste arbeiten, für diese Fälle können Sie lodash.uniq verwenden.
– JohnnyQ
21. Februar um 21:43 Uhr
Josh Mc
Oder für diejenigen, die einen Einzeiler suchen (einfach und funktional) kompatibel mit aktuellen Browsern:
let a = ["1", "1", "2", "3", "3", "1"];
let unique = a.filter((item, i, ar) => ar.indexOf(item) === i);
console.log(unique);
Aktualisierung 2021
Ich würde empfehlen, die Antwort von Charles Clayton zu lesen, da es seit den jüngsten Änderungen an JS noch prägnantere Möglichkeiten gibt, dies zu tun.
Aktualisierung 18.04.2017
Es scheint, als ob ‘Array.prototype.includes’ jetzt weit verbreitete Unterstützung in den neuesten Versionen der Mainline-Browser (Kompatibilität)
Aktualisierung 29.07.2015:
Es gibt Pläne für Browser, eine standardisierte ‘Array.prototype.includes’-Methode zu unterstützen, die diese Frage zwar nicht direkt beantwortet; ist oft verwandt.
// https://tc39.github.io/ecma262/#sec-array.prototype.includes
if (!Array.prototype.includes) {
Object.defineProperty(Array.prototype, 'includes', {
value: function(searchElement, fromIndex) {
// 1. Let O be ? ToObject(this value).
if (this == null) {
throw new TypeError('"this" is null or not defined');
}
var o = Object(this);
// 2. Let len be ? ToLength(? Get(O, "length")).
var len = o.length >>> 0;
// 3. If len is 0, return false.
if (len === 0) {
return false;
}
// 4. Let n be ? ToInteger(fromIndex).
// (If fromIndex is undefined, this step produces the value 0.)
var n = fromIndex | 0;
// 5. If n ≥ 0, then
// a. Let k be n.
// 6. Else n < 0,
// a. Let k be len + n.
// b. If k < 0, let k be 0.
var k = Math.max(n >= 0 ? n : len - Math.abs(n), 0);
// 7. Repeat, while k < len
while (k < len) {
// a. Let elementK be the result of ? Get(O, ! ToString(k)).
// b. If SameValueZero(searchElement, elementK) is true, return true.
// c. Increase k by 1.
// NOTE: === provides the correct "SameValueZero" comparison needed here.
if (o[k] === searchElement) {
return true;
}
k++;
}
// 8. Return false
return false;
}
});
}
Es ist fast Copy-Paste von Kennebec, aber zugegebenermaßen wird das Übergeben des Arrays als Parameter anstelle der Verwendung des Closures wahrscheinlich die Leistung verbessern.
– Benutzer1115652
4. Januar 2015 um 21:10 Uhr
– muss sagen, dass ich die Punkte nicht verbunden habe, einfach nach einem Einzeiler durchsucht habe, wie ein großer Post aussah, der so übersprungen wurde, eine alternative Quelle gefunden und neu gepostet hat, damit andere sie schnell finden können. Das heißt, Ihr Recht; so ziemlich das gleiche wie kennebec.
– Josh Mc
4. Januar 2015 um 22:34 Uhr
Nett — Wusste nicht, dass der Filter das Array als Parameter gesendet hat, und wollte nicht an einem externen Objekt arbeiten. Das ist genau das, was ich brauche – meine Version von Javascript (ältere Xerces-Version) wird die neuen Extras für eine Weile nicht haben.
– Gerard ONeill
25. April 2017 um 23:19 Uhr
@GerardONeill ja, in manchen Situationen ist es sehr wichtig, z. B. wenn es funktional verkettet ist und Sie Zugriff auf ein Array haben möchten, dem keine Variable wie .map(…).filter(…) zugewiesen wurde.
– Josh Mc
26. April 2017 um 5:03 Uhr
Schreckliche Antwort. O(N^2) Komplexität. Verwenden Sie dies nicht.
– Timmm
14. Mai 2020 um 11:35 Uhr
Jackwander
Da ich in den Kommentaren zur Antwort von @Rocket weiter darauf eingegangen bin, kann ich auch ein Beispiel angeben, das keine Bibliotheken verwendet. Dies erfordert zwei neue Prototypfunktionen, contains und unique
Array.prototype.contains = function(v) {
for (var i = 0; i < this.length; i++) {
if (this[i] === v) return true;
}
return false;
};
Array.prototype.unique = function() {
var arr = [];
for (var i = 0; i < this.length; i++) {
if (!arr.contains(this[i])) {
arr.push(this[i]);
}
}
return arr;
}
var duplicates = [1, 3, 4, 2, 1, 2, 3, 8];
var uniques = duplicates.unique(); // result = [1,3,4,2,8]
console.log(uniques);
Für mehr Zuverlässigkeit können Sie ersetzen contains mit MDNs indexOf Shim und prüfen, ob jedes Element ist indexOf ist gleich -1: Dokumentation
Danke für die Beispiele. Ich werde sie verwenden, um Optionen für ein Auswahlfeld zu filtern. Das sollte gut funktionieren.
– Astronaut
28. Juni 2012 um 16:10 Uhr
dies hat eine hohe Laufzeitkomplexität (worst case: O(n^2) )
– Rahul Arora
21. Oktober 2017 um 8:40 Uhr
Dies ist eine wirklich ineffiziente Implementierung. Das Überprüfen des Ergebnisarrays, um festzustellen, ob es bereits ein Element enthält, ist schrecklich. Ein besserer Ansatz wäre, entweder ein Objekt zu verwenden, das die Zählungen verfolgt, oder wenn Sie keinen Aux-Speicher verwenden möchten, sortieren Sie es zuerst in O (n log n) und dann in einen linearen Sweep und vergleichen Sie die Elemente nebeneinander
– Jesaja Lee
17. Dezember 2017 um 2:50 Uhr
Brauchen wir wirklich die „Contains“-Funktion?
– Animesh Kumar
18. März 2018 um 8:42 Uhr
Array.from(new Set(arr)) ist enorm Schneller: jsperf.com/unique-func-vs-set/1 — Um fair zu sein, das war vielleicht eine gute Antwort, als es geschrieben wurde, aber Sie sollte nicht benutze es jetzt.
– Kodierer
23. Juli 2020 um 8:49 Uhr
Vamsi
Ein Liner, reines JavaScript
Mit ES6-Syntax
list = list.filter((x, i, a) => a.indexOf(x) === i)
x --> item in array
i --> index of item
a --> array reference, (in this case "list")
Mit ES5-Syntax
list = list.filter(function (x, i, a) {
return a.indexOf(x) === i;
});
Browser-Kompatibilität: IE9+
Mit EcmaScript 2016 können Sie das einfach so machen.
var arr = ["a", "a", "b"];
var uniqueArray = Array.from(new Set(arr)); // Unique Array ['a', 'b'];
Sets sind immer einzigartig und verwenden Array.from() Sie können ein Set in ein Array konvertieren. Als Referenz werfen Sie einen Blick auf die Dokumentationen.
Das ist die Antwort, die Sie verwenden sollten. indexOf() Antworten sind schrecklich, weil sie O(N^2) sind. Die Spread-Antworten sind in Ordnung, funktionieren aber nicht für große Arrays. Dies ist der beste Ansatz.
– Timmm
14. Mai 2020 um 11:37 Uhr
@Timmmm: Welche Spread-Antworten funktionieren nicht für große Arrays?
– Ry- ♦
12. August 2020 um 0:17 Uhr
Eigentlich glaube ich, dass ich mich geirrt habe. Ich dachte daran, wenn Leute so etwas tun Math.max(...foo) aber in einem Array ist es ok. indexOf ist trotzdem eine schreckliche Idee!
– Timmm
12. August 2020 um 13:11 Uhr
Fawntasia
Heutzutage können Sie den Set-Datentyp von ES6 verwenden, um Ihr Array in ein eindeutiges Set umzuwandeln. Wenn Sie dann Array-Methoden verwenden müssen, können Sie es wieder in ein Array umwandeln:
var arr = ["a", "a", "b"];
var uniqueSet = new Set(arr); // {"a", "b"}
var uniqueArr = Array.from(uniqueSet); // ["a", "b"]
//Then continue to use array methods:
uniqueArr.join(", "); // "a, b"
Das ist die Antwort, die Sie verwenden sollten. indexOf() Antworten sind schrecklich, weil sie O(N^2) sind. Die Spread-Antworten sind in Ordnung, funktionieren aber nicht für große Arrays. Dies ist der beste Ansatz.
– Timmm
14. Mai 2020 um 11:37 Uhr
@Timmmm: Welche Spread-Antworten funktionieren nicht für große Arrays?
– Ry- ♦
12. August 2020 um 0:17 Uhr
Eigentlich glaube ich, dass ich mich geirrt habe. Ich dachte daran, wenn Leute so etwas tun Math.max(...foo) aber in einem Array ist es ok. indexOf ist trotzdem eine schreckliche Idee!
– Timmm
12. August 2020 um 13:11 Uhr
Raketen-Hazmat
Wenn Sie das ursprüngliche Array intakt lassen möchten,
Sie benötigen ein zweites Array, um die eindeutigen Elemente des ersten zu enthalten.
Die meisten Browser haben Array.prototype.filter:
var unique= array1.filter(function(itm, i){
return array1.indexOf(itm)== i;
// returns true for only the first instance of itm
});
//if you need a 'shim':
Array.prototype.filter= Array.prototype.filter || function(fun, scope){
var T= this, A= [], i= 0, itm, L= T.length;
if(typeof fun== 'function'){
while(i<L){
if(i in T){
itm= T[i];
if(fun.call(scope, itm, i, T)) A[A.length]= itm;
}
++i;
}
}
return A;
}
Array.prototype.indexOf= Array.prototype.indexOf || function(what, i){
if(!i || typeof i!= 'number') i= 0;
var L= this.length;
while(i<L){
if(this[i]=== what) return i;
++i;
}
return -1;
}
8676700cookie-checkSo erhalten Sie eindeutige Werte in einem Array [duplicate]yes
stackoverflow.com/questions/5381621/… – beschreibt genau das, was Sie wollen, denke ich?
– SpaceBison
28. Juni 2012 um 14:24 Uhr
Sind Sie offen für die Verwendung der
underscore.js
Bücherei?– jakee
28. Juni 2012 um 14:29 Uhr
Eine Java-Hashmap ist im Grunde dasselbe wie ein Javascript-Objekt. Syntax ist {“Schlüssel”: “Wert”, “Schlüssel2”: “Wert2”}
– Jan
28. Juni 2012 um 14:29 Uhr
JavaScript/TypeScript-Sammlungs-APIs sind im Vergleich zu Scala schrecklich,
list.toSet
– Jordan Stewart
12. Dezember 2019 um 2:36 Uhr
Es hängt davon ab, was sich im Array befindet, wie Sie “Eindeutigkeit” definieren und wie groß Ihre Daten sind. Wenn es sich um Objekte handelt, unterscheidet sich der Code von Zahlen oder Zeichenfolgen, und wenn die Daten sehr groß sind, möchten Sie eher eine lineare als eine quadratische Lösung. Bitte geben Sie weitere Details an.
– ggorlen
15. September 2020 um 15:22 Uhr