C # Zestaw kolekcja?

487

Czy ktoś wie, czy istnieje dobry odpowiednik Setkolekcji Java w C #? Wiem, że można nieco naśladować zestaw za pomocą a Dictionarylub a HashTable, wypełniając, ale ignorując wartości, ale to nie jest zbyt elegancki sposób.

Omar Kooheji
źródło

Odpowiedzi:

141

Wypróbuj HashSet :

Klasa HashSet (Of T) zapewnia operacje zestawu o wysokiej wydajności. Zestaw to kolekcja, która nie zawiera zduplikowanych elementów, a której elementy nie mają określonej kolejności ...

Pojemność obiektu HashSet (Of T) to liczba elementów, które obiekt może pomieścić. Pojemność obiektu HashSet (Of T) automatycznie wzrasta, gdy elementy są dodawane do obiektu.

Klasa HashSet (Of T) jest oparta na modelu zbiorów matematycznych i zapewnia wysokowydajne operacje na zestawach podobne do uzyskiwania dostępu do kluczy kolekcji Dictionary (Of TKey, TValue) lub Hashtable . Mówiąc prościej, klasę HashSet (Of T) można uznać za kolekcję Dictionary (Of TKey, TValue) bez wartości.

Kolekcja HashSet (Of T) nie jest sortowana i nie może zawierać zduplikowanych elementów ...

Leahn Novash
źródło
8
Niestety, HashSets zostały dodane dopiero niedawno. Jeśli pracujesz w starszej wersji frameworka, będziesz musiał trzymać się munged Dictionary <> lub Hashtable.
Greg D,
412

Jeśli korzystasz z .NET 3.5, możesz użyć HashSet<T>. To prawda, że ​​.NET nie obsługuje zestawów tak dobrze jak Java.

W PowerCollections Wintellect może pomóc też.

Jon Skeet
źródło
16
Podejrzewam, że Set jest słowem kluczowym w niektórych językach, co może powodować problemy.
Jon Skeet
3
@Manish: Nie, nie jest. Patrz sekcja 2.4.3 specyfikacji C # 3. Ma tylko specjalne znaczenie dla właściwości.
Jon Skeet
28
Powód nazywania go HashSet, a nie tylko Set, jest taki sam jak w Javie - „Set” opisuje interfejs, podczas gdy „HashSet” opisuje konkretną implementację, to jest Set wspierany przez Hash Map. W ten sposób wiemy (lub zdecydowanie powinniśmy oczekiwać), że wstawianie i dostęp powinny zająć czas dostępu O (1) w porównaniu z „LinkedListSet”, który doprowadziłby nas do oczekiwania na wstawienie i dostęp zajmie czas O (n).
David Souther,
5
co masz na myśli mówiąc „.NET nie obsługuje zestawów tak dobrze jak Java”.? Czy ten zestaw jest w jakiś sposób niedoskonały w porównaniu z Javą?
Louis Rhys
34
@Louis: O którym zestawie mówisz? Java ma wiele różnych implementacji Seta dla różnych sytuacji. .NET miał jeden w .NET 3.5 (HashSet) i dwa w .NET 4 (HashSet i SortedSet). Fakt, że na początek musieliśmy czekać do .NET 3.5, jest dość zaskakujący.
Jon Skeet
26

Jeśli używasz platformy .NET 4.0 lub nowszej:

W razie potrzeby sortowania użyj SortedSet<T>. W przeciwnym razie, jeśli nie, użyj, HashSet<T>ponieważ służy O(1)do wyszukiwania i manipulowania operacjami. Natomiast SortedSet<T>służy O(log n)do wyszukiwania i manipulowania operacjami.

Derek W.
źródło
13

Używam otoki wokół Dictionary<T, object>, przechowując wartości zerowe w wartościach. Daje to O (1) dodawanie, wyszukiwanie i usuwanie na klawiszach, a do wszystkich celów i celów działa jak zestaw.

Thecoop
źródło
2
Musisz mieć na myśli, że jest to mniej więcej odpowiednik std :: unordered_set. std :: set jest zamówiony. Na przykład możesz szybko znaleźć punkt początkowy i końcowy zakresu i iterować od początku do końca, odwiedzając elementy w kolejności kluczowej. SortedDictionary jest z grubsza odpowiednikiem std :: set.
doug65536
11

Spójrz na PowerCollections na CodePlex. Oprócz Set i OrdersSet ma kilka innych przydatnych typów kolekcji, takich jak Deque, MultiDictionary, Bag, OrdersBag, OrdersDictionary i OrdersMultiDictionary.

Aby uzyskać więcej kolekcji, dostępna jest również ogólna biblioteka kolekcji C5 .

dpan
źródło
-5

Wiem, że to stary wątek, ale napotkałem ten sam problem i stwierdziłem, że HashSet jest bardzo zawodny, ponieważ biorąc pod uwagę to samo ziarno, GetHashCode () zwrócił różne kody. Pomyślałem więc, dlaczego nie skorzystać z Listy i ukryć metodę dodawania w ten sposób

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

Ponieważ List używa metody Równości wyłącznie w celu ustalenia równości, możesz zdefiniować metodę Równości w swoim typie T, aby upewnić się, że uzyskasz pożądane wyniki.

Bob Heck
źródło
13
Powodem, dla którego nie chcą korzystać z tego jest, ponieważ List.Containsjest O(n)złożoność co oznacza, że Addmetoda staje się teraz O(n)złożoności, jak również. Zakładając kolekcję wewnętrzny nie musi być zmieniany, Addzarówno Listi HashMappowinny być od O(1)złożoności. TLDR: To zadziała, ale jest hakujące i mniej wydajne.
Richard Marskell - Drackir
6
Jasne, jeśli twoje obiekty nie zwracają odpowiedniej wartości dla GetHashCode, nie powinieneś umieszczać ich w kontenerze opartym na haszowaniu. Lepiej byłoby naprawić GetHashCode niż użyć mniej wydajnego kontenera.
bmm6o