C # Sammlung setzen?


488

Weiß jemand, ob es ein gutes Äquivalent zu Javas SetSammlung in C # gibt? Ich weiß, dass Sie eine Menge mit a Dictionaryoder a etwas nachahmen können HashTable, indem Sie die Werte auffüllen, aber ignorieren, aber das ist keine sehr elegante Methode.

Antworten:


142

Versuchen Sie HashSet :

Die HashSet (Of T) -Klasse bietet leistungsstarke Set-Operationen. Ein Set ist eine Sammlung, die keine doppelten Elemente enthält und deren Elemente in keiner bestimmten Reihenfolge vorliegen ...

Die Kapazität eines HashSet (Of T) -Objekts ist die Anzahl der Elemente, die das Objekt enthalten kann. Die Kapazität eines HashSet (Of T) -Objekts erhöht sich automatisch, wenn dem Objekt Elemente hinzugefügt werden.

Die HashSet (Of T) -Klasse basiert auf dem Modell mathematischer Mengen und bietet leistungsstarke Mengenoperationen, die dem Zugriff auf die Schlüssel der Dictionary- (Of TKey, TValue) oder Hashtable- Sammlungen ähneln . In einfachen Worten kann die HashSet (Of T) -Klasse als eine Dictionary- Sammlung (Of TKey, TValue) ohne Werte betrachtet werden.

Eine HashSet (Of T) -Sammlung ist nicht sortiert und kann keine doppelten Elemente enthalten ...


8
Leider wurden HashSets erst kürzlich hinzugefügt. Wenn Sie in einer älteren Version des Frameworks arbeiten, müssen Sie sich an Ihr Munged Dictionary <> oder Ihre Hashtable halten.
Greg D

413

Wenn Sie .NET 3.5 verwenden, können Sie verwenden HashSet<T>. Es ist wahr, dass .NET nicht so gut für Sets geeignet ist wie Java.

Die Wintellect PowerCollections können ebenfalls hilfreich sein.


16
Ich vermute, dass Set in einigen Sprachen ein Schlüsselwort ist, das Probleme verursachen kann.
Jon Skeet

3
@ Manish: Nein, ist es nicht. Siehe Abschnitt 2.4.3 der C # 3-Spezifikation. Es hat nur eine besondere Bedeutung für Eigenschaften.
Jon Skeet

28
Der Grund für den Aufruf von HashSet anstelle von Set ist der gleiche wie in Java. "Set" beschreibt eine Schnittstelle, während "HashSet" eine Implementierung beschreibt. Dies ist ein Set, das von einer Hash-Map unterstützt wird. Auf diese Weise wissen wir (oder sollten stark erwarten), dass das Einfügen und der Zugriff O (1) -Zugriffszeit benötigen, im Gegensatz zu einem "LinkedListSet", was dazu führen würde, dass das Einfügen und der Zugriff O (n) -Zeit benötigen.
David Souther

5
Was meinst du mit ".NET ist nicht so gut für Sets geeignet wie Java."? Ist dieses Set im Vergleich zu Java irgendwie unvollkommen?
Louis Rhys

34
@ Louis: Über welches Set sprichst du? Java hat viele verschiedene Implementierungen von Set für verschiedene Situationen. .NET hatte eine in .NET 3.5 (HashSet) und zwei in .NET 4 (HashSet und SortedSet). Die Tatsache, dass wir zunächst auf .NET 3.5 warten mussten, ist ziemlich überraschend.
Jon Skeet

26

Wenn Sie .NET 4.0 oder höher verwenden:

In dem Fall, in dem Sie sortieren müssen, verwenden Sie SortedSet<T>. Wenn Sie dies nicht tun, verwenden Sie es, HashSet<T>da es O(1)zum Suchen und Bearbeiten von Vorgängen dient. Während SortedSet<T>ist O(log n)für die Suche und Operationen manipulieren.



13

Ich benutze einen Wrapper um a Dictionary<T, object>und speichere Nullen in den Werten. Dies gibt O (1) das Hinzufügen, Nachschlagen und Entfernen der Schlüssel und verhält sich in jeder Hinsicht wie ein Satz.


2
Sie müssen meinen, dass es in etwa std :: unordered_set entspricht. std :: set ist bestellt. Sie können beispielsweise schnell den Start- und Endpunkt eines Bereichs finden und vom Anfang bis zum Ende iterieren, indem Sie Elemente in Schlüsselreihenfolge aufrufen. SortedDictionary ist etwa vergleichbar mit std :: set.
Doug65536

11

Schauen Sie sich PowerCollections bei CodePlex an. Neben Set und OrderedSet gibt es noch einige andere nützliche Sammlungstypen wie Deque, MultiDictionary, Bag, OrderedBag, OrderedDictionary und OrderedMultiDictionary.

Für weitere Sammlungen gibt es auch die C5 Generic Collection Library .


-5

Ich weiß, dass dies ein alter Thread ist, aber ich hatte das gleiche Problem und fand HashSet sehr unzuverlässig, da GetHashCode () bei gleichem Startwert unterschiedliche Codes zurückgegeben hat. Also dachte ich mir, warum nicht einfach eine Liste verwenden und die Add-Methode so ausblenden

public class UniqueList<T> : List<T>
{
    public new void Add(T obj)
    {
        if(!Contains(obj))
        {
            base.Add(obj);
        }
    }
}

Da List die Equals-Methode ausschließlich zur Bestimmung der Gleichheit verwendet, können Sie die Equals-Methode für Ihren T-Typ definieren, um sicherzustellen, dass Sie die gewünschten Ergebnisse erhalten.


13
Der Grund, warum Sie dies nicht verwenden möchten, List.Containsliegt in der O(n)Komplexität, was bedeutet, dass Ihre AddMethode jetzt auch komplex wird O(n). Angenommen, die Größe der inneren Sammlung muss Addfür beide nicht geändert werden Listund HashMapsollte O(1)komplex sein. TLDR: Das wird funktionieren, aber es ist hackig und weniger effizient.
Richard Marskell - Drackir

6
Wenn Ihre Objekte keinen geeigneten Wert für GetHashCode zurückgeben, sollten Sie sie nicht in einen Hash-basierten Container einfügen. Es wäre besser, GetHashCode zu reparieren, als einen weniger effizienten Container zu verwenden.
Bmm6o
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.