Collezione C # Set?


488

Qualcuno sa se esiste un buon equivalente alla Setraccolta di Java in C #? So che puoi in qualche modo imitare un set usando a Dictionaryo a HashTablepopolando ma ignorando i valori, ma non è un modo molto elegante.

Risposte:


142

Prova HashSet :

La classe HashSet (Of T) fornisce operazioni di set ad alte prestazioni. Un set è una raccolta che non contiene elementi duplicati e i cui elementi non sono in un ordine particolare ...

La capacità di un oggetto HashSet (Of T) è il numero di elementi che l'oggetto può contenere. La capacità di un oggetto HashSet (Of T) aumenta automaticamente man mano che gli elementi vengono aggiunti all'oggetto.

La classe HashSet (Of T) si basa sul modello di set matematici e fornisce operazioni sui set ad alte prestazioni simili all'accesso alle chiavi delle raccolte Dictionary (Of TKey, TValue) o Hashtable . In termini semplici, la classe HashSet (Of T) può essere pensata come una raccolta Dictionary (Of TKey, TValue) senza valori.

Una raccolta HashSet (Of T) non è ordinata e non può contenere elementi duplicati ...


8
Sfortunatamente, gli Hashset non sono stati aggiunti solo di recente. Se si lavora in una versione precedente del framework, è necessario attenersi al dizionario munguto <> o Hashtable.
Greg D,

413

Se si utilizza .NET 3.5, è possibile utilizzare HashSet<T>. È vero che .NET non soddisfa i set come Java.

Anche i PowerCollections di Wintellect possono essere d'aiuto.


16
Sospetto che Set sia una parola chiave in alcune lingue, il che potrebbe causare problemi.
Jon Skeet,

3
@Manish: No non lo è. Vedere la sezione 2.4.3 della specifica C # 3. Ha solo un significato speciale per le proprietà.
Jon Skeet,

28
Il motivo per chiamarlo HashSet, anziché solo Set, è lo stesso di Java: "Set" descrive un'interfaccia, mentre "HashSet" descrive un'implementazione specifica, si tratta di un set supportato da una mappa hash. In questo modo, sappiamo (o dovremmo aspettarci fortemente) che l'inserimento e l'accesso debbano richiedere il tempo di accesso O (1), rispetto a un "LinkedListSet" che ci indurrebbe ad aspettarci l'inserimento e l'accesso per impiegare il tempo O (n).
David Souther,

5
cosa intendi con ".NET non soddisfa i set come Java invece". Questo set è in qualche modo imperfetto rispetto a quello di Java?
Louis Rhys,

34
@ Louis: Di quale set stai parlando? Java ha molte implementazioni diverse di Set per varie situazioni. .NET ne aveva uno in .NET 3.5 (HashSet) e due in .NET 4 (HashSet e SortedSet). Il fatto che abbiamo dovuto aspettare fino a quando .NET 3.5 per iniziare è piuttosto sorprendente.
Jon Skeet,

26

Se si utilizza .NET 4.0 o versioni successive:

Nel caso in cui sia necessario l'ordinamento, utilizzare SortedSet<T>. Altrimenti, in caso contrario, utilizzare HashSet<T>poiché è O(1)per le operazioni di ricerca e manipolazione. Considerando che SortedSet<T>è O(log n)per operazioni di ricerca e manipolazione.



13

Uso un wrapper attorno a a Dictionary<T, object>, memorizzando valori null nei valori. Questo dà O (1) aggiungere, cercare e rimuovere i tasti e, a tutti gli effetti, si comporta come un set.


2
Devi dire che è approssimativamente equivalente a std :: unordered_set. std :: set è stato ordinato. Ad esempio, puoi trovare rapidamente il punto iniziale e finale di un intervallo e iterare dall'inizio alla fine, visitando gli elementi nell'ordine delle chiavi. SortedDictionary è approssimativamente equivalente a std :: set.
Doug65536,


-5

So che questo è un vecchio thread, ma stavo riscontrando lo stesso problema e ho trovato HashSet molto inaffidabile perché, dato lo stesso seed, GetHashCode () ha restituito codici diversi. Quindi, ho pensato, perché non usare semplicemente un Elenco e nascondere il metodo di aggiunta in questo modo

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

Poiché Elenco utilizza il metodo Equals esclusivamente per determinare l'uguaglianza, è possibile definire il metodo Equals sul tipo T per assicurarsi di ottenere i risultati desiderati.


13
Il motivo per cui non vorresti usarlo è perché List.Containsè di O(n)complessità, il che significa che anche il tuo Addmetodo diventa O(n)complessità. Supponendo che la collezione interna non debba essere ridimensionata, Addper entrambi Liste HashMapdovrebbe essere di O(1)complessità. TLDR: funzionerà, ma è confuso e meno efficiente.
Richard Marskell - Drackir,

6
Certo, se i tuoi oggetti non restituiscono un valore appropriato per GetHashCode, non dovresti metterli in un contenitore basato su hash. Sarebbe meglio riparare GetHashCode piuttosto che usare un contenitore meno efficiente.
bmm6o
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.