Ich arbeite in JavaScript. Ich möchte eine Liste eindeutiger , ungeordneter Zeichenfolgenwerte mit den folgenden Eigenschaften speichern :
- ein schneller Weg zu fragen, ob A in der Liste ist?
- Ein schneller Weg, um 'A aus der Liste zu löschen, wenn es in der Liste vorhanden ist'.
- Ein schneller Weg, um 'A zur Liste hinzuzufügen, falls es noch nicht vorhanden ist'.
Was ich wirklich will, ist ein Set. Irgendwelche Vorschläge, wie man einen Satz in JavaScript am besten nachahmt?
In dieser Frage wird empfohlen, ein Objekt zu verwenden , bei dem die Schlüssel Eigenschaften speichern und alle Werte auf true gesetzt sind: Ist das ein sinnvoller Weg?
javascript
Richard
quelle
quelle
Antworten:
Wenn Sie in einer ES6-fähigen Umgebung programmieren (z. B. node.js, einem bestimmten Browser mit den von Ihnen benötigten ES6-Funktionen oder dem Transpilieren von ES6-Code für Ihre Umgebung), können Sie
Set
das in ES6 integrierte Objekt verwenden . Es hat sehr schöne Fähigkeiten und kann so verwendet werden, wie es direkt in Ihrer Umgebung ist.Für viele einfache Dinge in einer ES5-Umgebung funktioniert die Verwendung eines Objekts sehr gut. Wenn
obj
es sich um Ihr Objekt handelt undA
es sich um eine Variable handelt, die den Wert hat, mit dem Sie im Set arbeiten möchten, können Sie Folgendes tun:Initialisierungscode:
Frage 1: Ist
A
in der Liste:Frage 2: Löschen Sie 'A' aus der Liste, wenn es dort ist:
Frage 3: Fügen Sie 'A' zur Liste hinzu, falls es noch nicht vorhanden war
Der Vollständigkeit halber
A
ist der Test, ob er in der Liste enthalten ist, damit etwas sicherer:aufgrund eines möglichen Konflikts zwischen integrierten Methoden und / oder Eigenschaften auf dem Basisobjekt wie der
constructor
Eigenschaft.Seitenleiste auf ES6: Die aktuelle Arbeitsversion von ECMAScript 6 oder etwas, das als ES 2015 bezeichnet wird, verfügt über ein integriertes Set-Objekt . Es ist jetzt in einigen Browsern implementiert. Da sich die Browserverfügbarkeit im Laufe der Zeit ändert, können Sie in der Zeile
Set
in dieser ES6-Kompatibilitätstabelle nach dem aktuellen Status für die Browserverfügbarkeit suchen .Ein Vorteil des integrierten Set-Objekts besteht darin, dass nicht alle Schlüssel zu einer Zeichenfolge gezwungen werden, wie dies beim Objekt der Fall ist, sodass Sie sowohl 5 als auch "5" als separate Schlüssel verwenden können. Sie können Objekte sogar direkt im Set ohne Zeichenfolgenkonvertierung verwenden. In diesem Artikel werden einige der Funktionen und die MDN-Dokumentation zum Set-Objekt beschrieben.
Ich habe jetzt eine Polyfüllung für das ES6-Set-Objekt geschrieben, damit Sie diese jetzt verwenden können. Sie wird automatisch auf das integrierte Set-Objekt verschoben, wenn der Browser dies unterstützt. Dies hat den Vorteil, dass Sie ES6-kompatiblen Code schreiben, der bis zum IE7 zurückreicht. Es gibt jedoch einige Nachteile. Die ES6-Set-Schnittstelle nutzt die ES6-Iteratoren, sodass Sie beispielsweise Folgendes tun können,
for (item of mySet)
und durchläuft das Set automatisch für Sie. Diese Art von Sprachfunktion kann jedoch nicht über Polyfill implementiert werden. Sie können ein ES6-Set immer noch iterieren, ohne die neuen ES6-Sprachfunktionen zu verwenden. Ohne die neuen Sprachfunktionen ist es jedoch nicht so praktisch wie die andere Set-Oberfläche, die ich unten einfüge.Sie können entscheiden, welches für Sie am besten geeignet ist, nachdem Sie sich beide angesehen haben. Die ES6-Set-Polyfüllung finden Sie hier: https://github.com/jfriend00/ES6-Set .
Zu Ihrer Information, bei meinen eigenen Tests habe ich festgestellt, dass die Implementierung von Firefox v29 Set im aktuellen Entwurf der Spezifikation nicht vollständig auf dem neuesten Stand ist. Zum Beispiel können Sie keine
.add()
Methodenaufrufe verketten, wie in der Spezifikation beschrieben und meine Polyfill unterstützt. Dies ist wahrscheinlich eine Frage einer Spezifikation in Bewegung, da sie noch nicht abgeschlossen ist.Vorgefertigte Set-Objekte: Wenn Sie ein bereits erstelltes Objekt mit Methoden zum Bearbeiten eines Sets möchten, das Sie in jedem Browser verwenden können, können Sie eine Reihe verschiedener vorgefertigter Objekte verwenden, die verschiedene Arten von Sets implementieren. Es gibt ein miniSet, einen kleinen Code, der die Grundlagen eines festgelegten Objekts implementiert. Es verfügt außerdem über ein funktionsreicheres Set-Objekt und mehrere Ableitungen, darunter ein Dictionary (speichern / rufen Sie einen Wert für jeden Schlüssel ab) und ein ObjectSet (behalten Sie eine Reihe von Objekten bei - entweder JS-Objekte oder DOM-Objekte, in denen Sie entweder das angeben Funktion, die für jeden einen eindeutigen Schlüssel generiert, oder das ObjectSet generiert den Schlüssel für Sie).
Hier ist eine Kopie des Codes für das miniSet (der aktuellste Code ist hier auf Github ).
quelle
Object.keys(obj)
.Object.keys()
benötigt IE9, FF4, Safari 5, Opera 12 oder höher. Es gibt eine polyfill für älteren Browser hier .obj.hasOwnProperty(prop)
für Mitgliedschaftsprüfungen verwenden. Verwenden SieObject.prototype.hasOwnProperty.call(obj, prop)
stattdessen, was auch dann funktioniert, wenn das "Set" den Wert enthält"hasOwnProperty"
.Sie können ein Objekt ohne Eigenschaften wie erstellen
Dies kann als Set fungieren und macht die Verwendung überflüssig
hasOwnProperty
.quelle
set = {}
, erbt es alle Eigenschaften von Object (z. B.toString
), sodass Sie die Nutzlast des Sets (Eigenschaften, die Sie hinzugefügt haben) mithasOwnProperty
inif (A in set)
set[A]=true
für jedes Element, das Sie hinzufügen möchten, Anweisungen haben müssen , anstatt nur einen Initialisierer?s = Object.create(null);s["thorben"] = true;ss = Object.create(s)
Ab ECMAScript 6 ist die Set-Datenstruktur eine integrierte Funktion . Die Kompatibilität mit den Versionen von node.js finden Sie hier .
quelle
in
funktioniert nicht, weilSet
Objekte ihre Elemente nicht als Eigenschaften haben, was schlecht wäre, da Mengen Elemente eines beliebigen Typs haben können, aber Eigenschaften Zeichenfolgen sind. Sie können verwendenhas
:Set([1,2]).has(1)
In der ES6-Version von Javascript haben Sie den Typ für set integriert ( überprüfen Sie die Kompatibilität mit Ihrem Browser ).
Um hinzuzufügen , ein Element der Menge , verwenden Sie einfach
.add()
, das ausgeführt wirdO(1)
und entweder das zu setzende Element hinzufügt (falls es nicht vorhanden ist) oder nichts tut, wenn es bereits vorhanden ist. Sie können dort Elemente eines beliebigen Typs hinzufügen (Arrays, Strings, Zahlen).So überprüfen Sie die Anzahl der Elemente im Set , können Sie einfach verwenden
.size
. Läuft auch inO(1)
So entfernen Sie das Element aus dem Set verwenden Sie
.delete()
. Es gibt true zurück, wenn der Wert vorhanden war (und entfernt wurde), und false, wenn der Wert nicht vorhanden war. Läuft auch inO(1)
.Um zu überprüfen, ob das Element in einer Menge vorhanden ist, verwenden Sie
.has()
, was true zurückgibt, wenn sich das Element in der Menge befindet, andernfalls false. Läuft auch inO(1)
.Zusätzlich zu den von Ihnen gewünschten Methoden gibt es nur wenige zusätzliche:
numbers.clear();
würde einfach alle Elemente aus dem Set entfernennumbers.forEach(callback);
Durchlaufen der Werte des Satzes in Einfügereihenfolgenumbers.entries();
Erstellen Sie einen Iterator aller Wertenumbers.keys();
Gibt die Schlüssel des Sets zurück, die mit identisch sindnumbers.values()
Es gibt auch ein Weakset, mit dem nur Objekttypwerte hinzugefügt werden können.
quelle
.add()
Läufe in O (1) verweisen ? Ich bin fasziniert davon,Ich habe eine Implementierung von Sets gestartet, die derzeit ziemlich gut mit Zahlen und Zeichenfolgen funktioniert. Mein Hauptaugenmerk lag auf der Differenzoperation, deshalb habe ich versucht, sie so effizient wie möglich zu gestalten. Gabeln und Code-Bewertungen sind willkommen!
https://github.com/mcrisc/SetJS
quelle
Mir ist gerade aufgefallen, dass in der Bibliothek d3.js Mengen, Karten und andere Datenstrukturen implementiert sind. Ich kann nicht über ihre Effizienz streiten, aber nach der Tatsache zu urteilen, dass es sich um eine beliebte Bibliothek handelt, muss es das sein, was Sie brauchen.
Die Dokumentation finden Sie hier
Der Einfachheit halber kopiere ich vom Link (die ersten 3 Funktionen sind von Interesse)
Erstellt einen neuen Satz. Wenn ein Array angegeben ist, wird das angegebene Array von Zeichenfolgenwerten zum zurückgegebenen Satz hinzugefügt.
Gibt nur dann true zurück, wenn diese Menge einen Eintrag für die angegebene Wertzeichenfolge enthält.
Fügt diesem Satz die angegebene Wertzeichenfolge hinzu.
Wenn die Menge die angegebene Wertzeichenfolge enthält, wird sie entfernt und true zurückgegeben. Andernfalls führt diese Methode nichts aus und gibt false zurück.
Gibt ein Array der Zeichenfolgenwerte in dieser Gruppe zurück. Die Reihenfolge der zurückgegebenen Werte ist beliebig. Kann als bequeme Methode zur Berechnung der eindeutigen Werte für eine Reihe von Zeichenfolgen verwendet werden. Beispielsweise:
d3.set (["foo", "bar", "foo", "baz"]). values (); // "foo", "bar", "baz"
Ruft die angegebene Funktion für jeden Wert in dieser Menge auf und übergibt den Wert als Argument. Der this-Kontext der Funktion ist diese Menge. Gibt undefiniert zurück. Die Iterationsreihenfolge ist beliebig.
Gibt nur dann true zurück, wenn diese Menge Nullwerte hat.
Gibt die Anzahl der Werte in diesem Satz zurück.
quelle
Ja, das ist ein vernünftiger Weg - das ist alles, was ein Objekt ist (nun, für diesen Anwendungsfall) - eine Reihe von Schlüsseln / Werten mit direktem Zugriff.
Sie müssen überprüfen, ob es bereits vorhanden ist, bevor Sie es hinzufügen, oder wenn Sie nur die Anwesenheit anzeigen müssen, ändert das erneute "Hinzufügen" nichts, sondern setzt es einfach erneut auf das Objekt.
quelle