Frage Alle eindeutigen Werte in einem JavaScript-Array abrufen (Duplikate entfernen)


Ich habe eine Reihe von Zahlen, die ich sicherstellen muss, dass sie einzigartig sind. Ich habe das Code-Snippet unten im Internet gefunden und es funktioniert großartig, bis das Array eine Null enthält. ich fand dieses andere Skript Hier auf SO sieht das fast genau so aus, aber es scheitert nicht.

Um mir beim Lernen zu helfen, kann mir jemand helfen, festzustellen, wo das Prototypskript schief läuft?

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 der doppelten Frage:

Ähnliche Frage:


779
2017-12-25 04:28


Ursprung


Antworten:


Mit JavaScript 1.6 / ECMAScript 5 Sie können das Native verwenden filter Methode eines Arrays auf die folgende Weise, um ein Array mit eindeutigen Werten zu erhalten:

function onlyUnique(value, index, self) { 
    return self.indexOf(value) === index;
}

// usage example:
var a = ['a', 1, 'a', 2, '1'];
var unique = a.filter( onlyUnique ); // returns ['a', 1, 2, '1']

Die native Methode filter Durchläuft das Array und lässt nur die Einträge zurück, die die angegebene Callback-Funktion durchlaufen haben onlyUnique.

onlyUnique prüft, ob der angegebene Wert der erste ist. Wenn nicht, muss es ein Duplikat sein und wird nicht kopiert.

Diese Lösung funktioniert ohne zusätzliche Bibliotheken wie jQuery oder prototype.js.

Es funktioniert auch für Arrays mit gemischten Werttypen.

Für alte Browser (<ie9), die die nativen Methoden nicht unterstützen filter und indexOf Arbeitsumgebungen finden Sie in der MDN-Dokumentation für Filter und Index von.

Wenn Sie das letzte Vorkommen eines Wertes beibehalten möchten, ersetzen Sie einfach indexOf durch lastIndexOf.

Mit ES6 könnte es sich verkürzen:

// usage example:
var myArray = ['a', 1, 'a', 2, '1'];
var unique = myArray.filter((v, i, a) => a.indexOf(v) === i); 

// unique is ['a', 1, 2, '1']

Dank an Camilo Martin für einen Hinweis im Kommentar.

ES6 hat ein natives Objekt Set um eindeutige Werte zu speichern. Um ein Array mit eindeutigen Werten zu erhalten, könnten Sie jetzt folgendes tun:

var myArray = ['a', 1, 'a', 2, '1'];

let unique = [...new Set(myArray)]; 

// unique is ['a', 1, 2, '1']

Der Konstruktor von Set nimmt ein iterables Objekt, wie Array, und den Spread-Operator ... transformiere den Satz zurück in ein Array. Dank an Lukas Liese für einen Hinweis im Kommentar.


1465
2018-01-21 12:46



Aktualisierte Antwort für ES6 / ES2015: Verwendung der einstellenDie Ein-Zeilen-Lösung ist:

var items = [4,5,4,6,3,4,5,2,23,1,4,4,4]
var uniqueItems = Array.from(new Set(items))

Was zurückkommt

[4, 5, 6, 3, 2, 23, 1]

Wie le_m vorgeschlagen, kann dies auch verkürzt werden mit Spread-Operator , mögen

var uniqueItems = [...new Set(items)]

488
2017-10-14 09:42



Sie können auch verwenden Unterstrich.js.

console.log(_.uniq([1, 2, 1, 3, 1, 4]));
<script src="http://underscorejs.org/underscore-min.js"></script>

was zurückkommt:

[1, 2, 3, 4]

116
2017-07-11 16:25



Ich weiß, dass diese Frage bereits mehr als 30 Antworten hat. Aber ich habe zuerst alle vorhandenen Antworten durchgelesen und selbst recherchiert.

Ich teile alle Antworten auf 4 mögliche Lösungen:

  1. Verwenden Sie die neue ES6-Funktion: [...new Set( [1, 1, 2] )];
  2. Verwenden Sie ein Objekt { } Duplikate verhindern
  3. Verwenden Sie Helfer-Array [ ]
  4. Benutzen filter + indexOf

Hier sind Beispielcodes in den Antworten:

Verwenden Sie die neue ES6-Funktion: [...new Set( [1, 1, 2] )];

function uniqueArray0(array) {
  var result = Array.from(new Set(array));
  return result    
}

Verwenden Sie ein Objekt { } Duplikate verhindern

function uniqueArray1( ar ) {
  var j = {};

  ar.forEach( function(v) {
    j[v+ '::' + typeof v] = v;
  });

  return Object.keys(j).map(function(v){
    return j[v];
  });
} 

Verwenden Sie Helfer-Array [ ]

function uniqueArray2(arr) {
    var a = [];
    for (var i=0, l=arr.length; i<l; i++)
        if (a.indexOf(arr[i]) === -1 && arr[i] !== '')
            a.push(arr[i]);
    return a;
}

Benutzen filter + indexOf

function uniqueArray3(a) {
  function onlyUnique(value, index, self) { 
      return self.indexOf(value) === index;
  }

  // usage
  var unique = a.filter( onlyUnique ); // returns ['a', 1, 2, '1']

  return unique;
}

Und ich habe mich gefragt, welcher schneller ist. Ich habe gemacht Beispiel Google Sheet um Funktionen zu testen. Hinweis: ECMA 6 ist in Google Tabellen nicht verfügbar, daher kann ich es nicht testen.

Hier ist das Ergebnis der Tests: enter image description here

Ich habe erwartet, diesen Code mit dem Objekt zu sehen { } wird gewinnen, weil es Hash verwendet. Daher bin ich froh, dass die Tests in Chrome und IE die besten Ergebnisse für diesen Algorithmus gezeigt haben. Danke an @rab für der Code.


87
2018-03-27 12:24



Ich habe seitdem eine nette Methode gefunden, die jQuery verwendet

arr = $.grep(arr, function(v, k){
    return $.inArray(v ,arr) === k;
});

Hinweis: Dieser Code wurde aus gezogen Paul Irish's Entenschlagpfosten - Ich habe vergessen, Kredit zu geben: P


51
2017-07-12 15:41



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")

enter image description here

Mit ES5-Syntax

list = list.filter(function (x, i, a) { 
    return a.indexOf(x) == i; 
});

Browser-Kompatibilität: IE9 +


44
2017-09-01 13:32



Kürzeste Lösung mit ES6: [...new Set( [1, 1, 2] )];

Oder wenn Sie den Array-Prototyp modifizieren möchten (wie in der ursprünglichen Frage):

Array.prototype.getUnique = function() {
    return [...new Set( [this] )];
};

EcmaScript 6 ist nur teilweise implementiert in modernen Browsern im Moment (Aug. 2015), aber Babel ist sehr populär geworden, um ES6 (und sogar ES7) zurück zu ES5 zu transponieren. So können Sie heute ES6-Code schreiben!

Wenn Sie sich fragen, was ... bedeutet, es heißt die Spread-Operator. Von MDN: «Der Spread-Operator erlaubt es, einen Ausdruck an Stellen zu erweitern, an denen mehrere Argumente (für Funktionsaufrufe) oder mehrere Elemente (für Array-Literale) erwartet werden». Da ein Set ein iterabler Wert ist (und nur eindeutige Werte haben kann), erweitert der Spread-Operator das Set, um das Array zu füllen.

Ressourcen zum Lernen von ES6:


39
2018-04-23 12:42



Einfachste Lösung:

var arr = [1, 3, 4, 1, 2, 1, 3, 3, 4, 1];
console.log([...new Set(arr)]);

Oder:

var arr = [1, 3, 4, 1, 2, 1, 3, 3, 4, 1];
console.log(Array.from(new Set(arr)));


31
2018-03-14 22:01



Das einfachste und am schnellsten (in Chrome), um dies zu tun:

Array.prototype.unique = function() {
    var a = [];
    for (var i=0, l=this.length; i<l; i++)
        if (a.indexOf(this[i]) === -1)
            a.push(this[i]);
    return a;
}

Geht einfach durch jedes Element im Array, testet, ob dieses Element bereits in der Liste ist, und wenn es nicht ist, drücken Sie auf das Array, das zurückgegeben wird.

Laut jsPerf ist diese Funktion der schnellste von denen, die ich überall finden konnte - Fühlen Sie sich frei, Ihre eigenen hinzuzufügen.

Die Nicht-Prototyp-Version:

function uniques(arr) {
    var a = [];
    for (var i=0, l=arr.length; i<l; i++)
        if (a.indexOf(arr[i]) === -1 && arr[i] !== '')
            a.push(arr[i]);
    return a;
}

Sortierung

Wenn auch das Array sortiert werden muss, ist Folgendes am schnellsten:

Array.prototype.sortUnique = function() {
    this.sort();
    var last_i;
    for (var i=0;i<this.length;i++)
        if ((last_i = this.lastIndexOf(this[i])) !== i)
            this.splice(i+1, last_i-i);
    return this;
}

oder Nicht-Prototyp:

function sortUnique(arr) {
    arr.sort();
    var last_i;
    for (var i=0;i<arr.length;i++)
        if ((last_i = arr.lastIndexOf(arr[i])) !== i)
            arr.splice(i+1, last_i-i);
    return arr;
}

Das ist auch schneller als die oben genannte Methode in den meisten nicht-Chrome-Browsern.


30
2018-01-30 00:10



LEISTUNG NUR! Dieser Code ist wahrscheinlich 10x schneller als alle Codes hier * funktioniert auf allen Browsern und hat auch den geringsten Speicherverbrauch .... und mehr

Wenn Sie das alte Array nicht wiederverwenden müssen, dann machen Sie die notwendigen anderen Operationen, bevor Sie es in Unique konvertieren, ist wahrscheinlich der schnellste Weg, dies zu tun, auch sehr kurz.

var array=[1,2,3,4,5,6,7,8,9,0,1,2,1];

dann kannst du es versuchen

var array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 1];

function toUnique(a, b, c) { //array,placeholder,placeholder
  b = a.length;
  while (c = --b)
    while (c--) a[b] !== a[c] || a.splice(c, 1);
  return a // not needed ;)
}
console.log(toUnique(array));
//[3, 4, 5, 6, 7, 8, 9, 0, 2, 1]

Ich kam mit dieser Funktion diesen Artikel lesen ...

http://www.shamassis.net/2009/09/fast-algorithm-to-find-unique-items-in-javascript-array/

Ich mag die for-Schleife nicht. Es hat 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.

Wie auch immer, ich schrieb die erste Funktion, die While verwendet. Und yep, es ist ein wenig schneller als die Funktion im Artikel gefunden, aber nicht genug.unique2()

Nächster Schritt Verwenden Sie moderne js.Object.keys Ich habe die andere for-Schleife durch js1.7's Object.keys ersetzt ... etwas schneller und kürzer (in Chrom 2x schneller);). Nicht genug!.unique3().

An diesem Punkt 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 loops + splice benutzt.unique4()

Nutzlos zu sagen, dass ich beeindruckt war.

Chrom: die üblichen 150.000 Operationen pro Sekunde sprangen auf 1.800.000 Operationen pro Sekunde.

zB: 80.000 op / s vs 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 verwenden ... microtime ... was auch immer

unique5() dient nur dazu, Ihnen zu zeigen, was passiert, wenn Sie das alte Array behalten wollen.

Benutze es nicht Array.prototype wenn du nicht weißt, was du tust. Ich habe gerade viel Kopie und Vergangenheit. Benutzen Object.defineProperty(Array.prototype,...,writable:false,enumerable:false}) wenn Sie einen nativen Prototyp erstellen möchten.beispiel: https://stackoverflow.com/a/20463021/2450730

Demo http://jsfiddle.net/46S7g/

HINWEIS: Ihr altes Array wird nach diesem Vorgang zerstört / wird zu einem neuen Array.

Wenn Sie den obigen Code nicht lesen können, lesen Sie ein Javascript-Buch oder hier sind einige Erläuterungen zu kürzerem Code. https://stackoverflow.com/a/21353032/2450730

einige benutzen indexOf  ... nicht ... http://jsperf.com/dgfgghfghfghghgfhgfhfghfhgfh

für leere Arrays

!array.length||toUnique(array); 

29
2017-08-01 14:49



Viele der Antworten hier sind möglicherweise nicht für Anfänger nützlich. Wenn es schwierig ist, ein Array zu dedupfen, werden sie wirklich von der Prototypkette oder sogar jQuery wissen?

In modernen Browsern ist eine saubere und einfache Lösung, Daten in einem zu speichern einstellen, die als eine Liste eindeutiger Werte entworfen wurde.

const cars = ['Volvo', 'Jeep', 'Volvo', 'Lincoln', 'Lincoln', 'Ford'];
const uniqueCars = Array.from(new Set(cars));

Das Array.from ist nützlich, um das Set zurück in ein Array zu konvertieren, so dass Sie einfachen Zugriff auf all die tollen Methoden (Features) haben, die Arrays haben. Es gibt auch andere Möglichkeiten das Gleiche zu tun. Aber du brauchst es vielleicht nicht Array.from überhaupt, wie Sets viele nützliche Funktionen wie haben für jede.

Wenn Sie den alten Internet Explorer unterstützen müssen und daher Set nicht verwenden können, besteht eine einfache Technik darin, Elemente in ein neues Array zu kopieren, während Sie vorher prüfen, ob sie bereits im neuen Array vorhanden sind.

// Create a list of cars, with duplicates.
var cars = ['Volvo', 'Jeep', 'Volvo', 'Lincoln', 'Lincoln', 'Ford'];
// Create a list of unique cars, to put a car in if we haven't already.
var uniqueCars = [];

// Go through each car, one at a time.
cars.forEach(function (car) {
    // The code within the following block runs only if the
    // current car does NOT exist in the uniqueCars list
    // - a.k.a. prevent duplicates
    if (uniqueCars.indexOf(car) === -1) {
        // Since we now know we haven't seen this car before,
        // copy it to the end of the uniqueCars list.
        uniqueCars.push(car);
    }
});

Um es sofort wieder verwendbar zu machen, stellen wir es in eine Funktion.

function deduplicate(data) {
    if (data.length > 0) {
        var result = [];

        data.forEach(function (elem) {
            if (result.indexOf(elem) === -1) {
                result.push(elem);
            }
        });

        return result;
    }
}

Um die Duplikate loszuwerden, würden wir das jetzt tun.

var uniqueCars = deduplicate(cars);

Das deduplicate(cars) Teil wird das, was wir genannt haben Ergebnis wenn die Funktion beendet ist.

Übergeben Sie einfach den Namen eines Arrays, das Sie mögen.


23
2018-01-15 06:56