Möglichkeiten zum Erstellen eines Sets in JavaScript?

Lesezeit: 9 Minuten

Benutzer-Avatar
Hilfsmethode

In Eloquent JavaScript, Kapitel 4, wird eine Reihe von Werten erstellt, indem ein Objekt erstellt und die Werte als Eigenschaftsnamen gespeichert werden, wobei willkürliche Werte (z. B. wahr) als Eigenschaftswerte zugewiesen werden. Um zu prüfen, ob der Wert bereits im Set enthalten ist, kann die in Operator verwendet:

var set = {};

if (!'Tom' in set) { 
  set.Tom = true;
}

Ist das idiomatisches JavaScript? Wäre es nicht besser, ein Array zu verwenden?

var set = [];

if (!'Tom' in set) { 
  set.push="Tom";
}

  • Wie würden Sie ein Array erwarten, für das 'Tom' in set ist wahr, wie auszusehen? Es sieht sehr danach aus, als hättest du falsche Annahmen darüber etwasund ich versuche es herauszufinden worüber.

    Benutzer395760

    2. Dezember 2011 um 22:38 Uhr


  • Zu Ihrer Information, Sie brauchen Eltern: if(!('Tom' in set)). Aktuell heißt es false in set seit !'Tom' === false.

    – pimvdb

    2. Dezember 2011 um 22:41 Uhr


  • ES6 hat Sets, siehe Johns Antwort unten

    – Ben Taliadoros

    7. März 2016 um 16:14 Uhr

Benutzer-Avatar
John

Sätze sind jetzt in ES2015 (alias ES6, dh ECMAScript 6) verfügbar. ES6 ist seit Juni 2015 der aktuelle Standard für JavaScript.

ECMAScript 6 hat die Datenstruktur Set, die für beliebige Werte funktioniert, schnell ist und NaN korrekt behandelt. –Axel Rauschmayer, Erkundung von ES6

Zuerst zwei Beispiele aus Axel Rauschmayer Buchen Erkundung von ES6:

Einzelne Elemente verwalten:

> let set = new Set();
> set.add('red')

> set.has('red')
true
> set.delete('red')
true
> set.has('red')
false

Größe eines Sets bestimmen und löschen:

> let set = new Set();
> set.add('red')
> set.add('green')

> set.size
2
> set.clear();
> set.size
0

Ich würde auschecken Erkundung von ES6 wenn Sie mehr über Sets in JavaScript erfahren möchten. Das Buch kann kostenlos online gelesen werden, aber wenn Sie den Autor unterstützen möchten Dr. Axel Rauschmayer Sie können das Buch für etwa 30 $ kaufen.

Wenn Sie Sets und ES6 jetzt verwenden möchten, können Sie verwenden Babelder ES6-zu-ES5-Transpiler und seine Polyfills.

Bearbeiten: Ab dem 6. Juni 2017 haben die meisten großen Browser in ihren neuesten Versionen (außer IE 11) volle Set-Unterstützung. Das bedeutet, dass Sie babel möglicherweise nicht benötigen, wenn Sie ältere Browser nicht unterstützen möchten. Wenn Sie die Kompatibilität in verschiedenen Browsern einschließlich Ihres aktuellen Browsers überprüfen möchten Die ES6-Kompatibilitätstabelle von Kangax.

BEARBEITEN:

Nur eine Klarstellung zur Initialisierung. Sets können jedes synchrone Iterable in ihrem Konstruktor aufnehmen. Das bedeutet, dass sie nicht nur Arrays, sondern auch Strings und Iteratoren verwenden können. Nehmen Sie zum Beispiel die folgende Array- und String-Initialisierung eines Satzes:

const set1 = new Set(['a','a','b','b','c','c']);
console.log(...set1);
console.log(set1.size);
const set2 = new Set("aabbcc");
console.log(...set2);
console.log(set2.size);

Beide Ausgänge des Arrays und des Strings sind gleich. Beachten Sie, dass ...set1 ist der Spread-Syntax. Es scheint, dass jedes Element des iterierbaren Elements einzeln zum Set hinzugefügt wird. Da sowohl das Array als auch der String die gleichen Elemente haben und die Elemente in der gleichen Reihenfolge sind, wird das Set gleich erstellt. Eine weitere Sache, die bei Mengen zu beachten ist, ist, dass beim Iterieren über sie die Iterationsreihenfolge der Reihenfolge folgt, in der die Elemente in die Menge eingefügt wurden. Hier ist ein Beispiel für das Iterieren über eine Menge:

const set1 = new Set(['a','a','b','b','c','c']);
for(const element of set1) {
  console.log(element);
}

Da Sie jedes Iterable verwenden können, um eine Menge zu initialisieren, könnten Sie sogar einen Iterator von a verwenden Generatorfunktion. Hier sind zwei solcher Beispiele für Iterator-Initialisierungen, die dieselbe Ausgabe erzeugen:

// a simple generator example
function* getLetters1 () {
  yield 'a';
  yield 'a';
  yield 'b';
  yield 'b';
  yield 'c';
  yield 'c';
}

// a somewhat more commonplace generator example
// with the same output as getLetters1.
function* getLetters2 (letters, repeatTimes) {
  for(const letter of letters) {
    for(let i = 0; i < repeatTimes; ++i) { 
      yield letter;
    }
  }
}

console.log("------ getLetters1 ------");
console.log(...getLetters1());
const set3 = new Set(getLetters1());
console.log(...set3);
console.log(set3.size);

console.log("------ getLetters2 ------");
console.log(...getLetters2('abc', 2));
const set4 = new Set(getLetters2('abc', 2));
console.log(...set4);
console.log(set4.size);

Die Generatorfunktionen dieser Beispiele könnten einfach so geschrieben werden, dass sie sich nicht wiederholen, aber wenn die Generatorfunktion komplizierter ist und sich das Folgende nicht zu negativ auf die Leistung auswirkt, können Sie die Set-Methode verwenden, um nur Werte von einem Generator zu erhalten, der don nicht wiederholen.

Wenn Sie mehr über Mengen wissen möchten, ohne das Kapitel von Dr. Rauschmayer in seinem Buch gelesen zu haben, können Sie sich das ansehen MDN-Dokumente auf Set. MDN hat auch mehr Beispiele für das Iterieren über einen Satz, wie z. B. using forEach und mit der .keys, .valuesund .entries Methoden. MDN hat auch Beispiele wie Set Union, Set Intersection, Set Difference, Symmetric Set Difference und Set Superset Checking. Hoffentlich werden die meisten dieser Operationen in JavaScript verfügbar, ohne dass Sie Ihre eigenen Funktionen erstellen müssen, die sie unterstützen. Tatsächlich gibt es das dieser TC39-Vorschlag für neue Set-Methoden was hoffentlich zu einem späteren Zeitpunkt die folgenden Methoden zu Set in JavaScript hinzufügen sollte, wenn der Vorschlag Stufe 4 erreicht:

  • Set.prototype.intersection(iterable) – Methode erstellt eine neue Set-Instanz durch Set-Intersection-Operation.
  • Set.prototype.union(iterable) – Methode erstellt neue Set-Instanz durch Set-Vereinigungsoperation.
  • Set.prototype.difference(iterable) – Die Methode erstellt ein neues Set ohne Elemente, die in iterierbar vorhanden sind.
  • Set.prototype.symmetricDifference(iterable) – gibt eine Menge von Elementen zurück, die nur in this oder in iterable gefunden werden.
  • Set.prototype.isSubsetOf (iterierbar)
  • Set.prototype.isDisjointFrom (iterierbar)
  • Set.prototype.isSupersetOf (iterierbar)

  • Auch Sets selbst sind iterierbar, sodass Sie Sets mit anderen Sets initialisieren können, um eine Kopie zu erstellen, oder so etwas wie new Set([…setA, …setB]) für einen Gewerkschaftsbetrieb.

    – John

    1. Oktober 2019 um 19:52 Uhr

  • @LanceKind Ich habe einige zusätzliche Informationen hinzugefügt, einschließlich des Zeigens, dass Sie Sätze mit beliebigen iterierbaren nicht nur Arrays initialisieren können.

    – John

    1. Oktober 2019 um 20:01 Uhr

Ich verwende dict-Objekte als Sets. Dies funktioniert mit Zeichenfolgen und Zahlen, aber ich nehme an, es würde Probleme verursachen, wenn Sie eine Reihe von Objekten mit benutzerdefinierten Gleichheits- und Vergleichsoperatoren haben möchten:

Set erstellen:

var example_set = 
{
    'a':true,
    'b':true,
    'c':true
}

Prüfung auf Aufnahme in einen Satz

if( example_set['a'] ){
    alert('"a" is in set');
}

Hinzufügen eines Elements zu einer Menge

example_set['d'] = true;

Entfernen eines Elements aus einer Menge

delete example_set['a'];

  • Der Code, an dem ich arbeitete, verwendete eine ältere Version der Engine, die keine Unterstützung hatte Set. Das hat geholfen.

    – Abhijith Madhav

    29. Dezember 2016 um 14:01 Uhr

  • Wenn Sie TypeScript verwendet haben, welchen Typ würden Sie verwenden? example_set?

    – Bitte Arbeit

    23. Februar um 20:53 Uhr


Sätze erlauben keine doppelten Einträge und garantieren normalerweise keine vordefinierte Reihenfolge. Arrays tun beides und verletzen damit, was es bedeutet, eine Menge zu sein (es sei denn, Sie führen zusätzliche Überprüfungen durch).

  • Array filtert keine doppelten Einträge … zum Beispiel arr.push ({id:1, name: “Jake”}) wie als NSSet in Objective-C 🙂

    – iTux

    14. Dezember 2015 um 16:43 Uhr


  • Wenn Sie es mot-a-mot nehmen, nein. Aber Sie können einfach die ID als Array (Map)-Schlüssel verwenden. arr[id] = {"name": "Jake"};

    – Büffel

    4. Mai 2017 um 6:39 Uhr


Der erste Weg ist idiomatisches JavaScript.

Jedes Mal, wenn Sie ein Schlüssel/Wert-Paar speichern möchten, müssen Sie ein JavaScript-Objekt verwenden. Bei Arrays gibt es mehrere Probleme:

  1. Der Index ist ein numerischer Wert.

  2. Keine einfache Möglichkeit zu überprüfen, ob sich ein Wert in einem Array befindet, ohne es zu durchlaufen.

  3. Ein Set erlaubt keine Duplikate. Ein Array tut es.

Benutzer-Avatar
Benjaminz

Wenn Sie einen Satz aus einem Array erstellen möchten, tun Sie einfach Folgendes:

let arr = [1, 1, 2, 1, 3];
let mySet = new Set(arr); // Set { 1, 2, 3 }

Dies ist eine Zuckersyntax, die mir beim Programmieren in Python sehr gut gefallen hat, und ich bin so froh, dass ES6 es endlich ermöglicht hat, dasselbe zu tun.

HINWEIS: Dann wird mir klar, dass das, was ich gesagt habe, Ihre Frage nicht direkt beantwortet hat. Der Grund, warum Sie diesen “Hack” in ES5 haben, liegt darin, dass die Suchzeit in einem Objekt nach Schlüsseln erheblich schneller ist (O (1)) als in einem Array (O (n)). In leistungskritischen Anwendungen können Sie dieses bisschen Lesbarkeit oder Intuition für eine bessere Leistung opfern.

Aber hey, willkommen im Jahr 2017, wo Sie richtig verwenden können Satz jetzt in allen gängigen modernen Browsern!

Benutzer-Avatar
Willem van der Veen

Spielt in ES6/ES2015:

ES6/ES2015 hat jetzt eingebaute Sätze. Ein Satz ist eine Datenstruktur, die das Speichern von eindeutigen Werten beliebigen Typs ermöglicht, unabhängig davon, ob es sich um primitive Werte oder Objektreferenzen handelt. Eine Menge kann mit deklariert werden ES6 Eingebauter Set-Konstruktor auf folgende Weise:

const set = new Set([1, 2, 3, 4, 5]);

Beim Erstellen eines Sets mit dem Set-Konstruktor erbt unser neu erstelltes Set-Objekt von der Set.prototype. Diese hat allerlei Hilfsmethoden und Eigenschaften. Damit können Sie ganz einfach die folgenden Dinge tun:

Beispiel:

const set = new Set([1, 2, 3, 4, 5]);

// checkout the size of the set
console.log('size is: ' + set.size);

// has method returns a boolean, true if the item is in the set
console.log(set.has(1));

// add a number
set.add(6);

// delete a number
set.delete(1);

// iterate over each element using a callback
set.forEach((el) => {
  console.log(el);
});

// remove all the entries from the set
set.clear();

Browser-Kompatibilität:

Alle gängigen Browser unterstützen jetzt Sets vollständig, mit Ausnahme von IE, wo einige Funktionen fehlen. Den genauen Bezug entnehmen Sie bitte der mdn-Dokumente.

Benutzer-Avatar
georg

Es gibt zwei Probleme bei der Verwendung von nackten Javascript-Objekten zur Emulation von Mengen: Erstens kann ein Objekt eine geerbte Eigenschaft haben, die den “in” -Operator vermasseln würde, und zweitens können Sie auf diese Weise nur skalare Werte speichern, eine Menge von Objekten jedoch nicht möglich. Daher sollte eine realistische Implementierung von Sets Methoden bereitstellen add und contains statt schlicht in und Grundstücksabtretungen.

  • @kojiro: Objekte werden in Zeichenfolgen konvertiert, wenn sie als Schlüssel verwendet werden: set={};set[{x:1}]=123;alert(set[{z:99}])

    – georg

    25. Dezember 2011 um 9:48 Uhr

1175310cookie-checkMöglichkeiten zum Erstellen eines Sets in JavaScript?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy