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.

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 ...


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ż.


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.



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.


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 .


-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.


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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.