Ruby: Will ein Set-ähnliches Objekt, das Ordnung erhält

8

... oder alternativ ein Array, das doppelte Einträge verhindert.

Gibt es in Ruby ein Objekt, das:

  • antwortet auf [], [] = und & lt; & lt;
  • löscht automatisch doppelte Einträge
  • ist Enumerable (oder unterstützt mindestens find_all)
  • behält die Reihenfolge bei, in der Einträge eingefügt wurden
?

Soweit ich das beurteilen kann, unterstützt ein Array die Punkte 1, 3 und 4; während ein Set 1, 2 und 3 unterstützt (aber nicht 4). Und ein SortedSet wird nicht tun, weil meine Einträge & lt; = & gt;.

nicht implementieren     
Chowlett 21.04.2009, 16:11
quelle

5 Antworten

6

Soweit ich weiß, gibt es keins, und Set ist aufgrund seiner mathematischen Natur dazu gedacht, ungeordnet (oder zumindest implementativ, nicht um Ordnung zu garantieren) zu sein - tatsächlich wird es normalerweise als Hash-Tabelle implementiert Ordnung versauen).

Es ist jedoch nicht schwer, entweder das Array direkt zu erweitern oder dafür eine Unterklasse zu erstellen. Ich habe es gerade ausprobiert und das funktioniert:

%Vor%

Scheint alle Grundlagen abzudecken. Ich habe OReillys praktisches Ruby-Kochbuch als Referenz benutzt - sie haben ein Rezept für "Sicherstellen, dass ein sortiertes Array sortiert bleibt", was ähnlich ist.

    
Rhubarb 21.04.2009, 18:25
quelle
12

Ab Ruby 1.9 behält das integrierte Objekt Hash die Reihenfolge der Einfügung bei. Zum Beispiel:

%Vor%

Sie können also einen beliebigen Wert (wie eine einfache true ) für einen beliebigen Schlüssel festlegen und haben jetzt eine geordnete Menge. Sie können mit h.key?(obj) auf einen Schlüssel testen oder, wenn Sie für jeden Schlüssel immer einen Truthy-Wert festlegen, nur h[obj] . Um einen Schlüssel zu entfernen, verwenden Sie h.delete(obj) . Um die geordnete Menge in ein Array zu konvertieren, verwenden Sie h.keys .

Weil die Ruby 1.9 Set -Bibliothek Set als geordneten Satz verwenden. (Beispielsweise ist die Implementierung der to_a -Methode nur @hash.keys .) Beachten Sie jedoch, dass dieses Verhalten nicht von dieser Bibliothek garantiert wird und sich möglicherweise in ändert Zukunft.

%Vor%     
Phrogz 22.01.2013 21:47
quelle
6

Ich mag diese Lösung, obwohl sie OrderedHash von active_support benötigt.

%Vor%

=)

    
user555536 09.12.2011 20:56
quelle
1

Sie können einen Hash verwenden, um die Werte zu speichern, und Sie haben einen inkrementierenden Wert, der im Wert jedes Hash-Paares gespeichert ist. Dann können Sie, wenn auch langsam, auf die Menge zugreifen, indem Sie über ihre Werte auf die Objekte zugreifen.

Ich werde später versuchen, etwas Code hinzuzufügen, um es weiter zu erklären.

Ich weiß, dass der Zugriff über Werte viel langsamer ist als über Tasten.

Update 1: In Ruby 1.9 werden Hash-Elemente in ihrer Reihenfolge wiederholt.

    
Matthew Schinckel 21.04.2009 22:57
quelle
0

Nicht, dass ich davon wüsste, aber es wäre nicht schwer, das eigene zu rollen. Unterordnen Sie Array einfach und verwenden Sie ein Set, um Ihre Eindeutigkeitseinschränkung beizubehalten.

Eine Frage zum stillen Ablegen. Wie wirkt sich das auf # [] =? Wenn ich einen vorhandenen Eintrag mit etwas überschreiben wollte, das bereits an anderer Stelle gespeichert wurde, sollte es das Element entfernen, das entfernt werden soll? Ich denke, dass jeder Weg böse Überraschungen auf der Straße bieten könnte.

    
rampion 21.04.2009 18:24
quelle

Tags und Links