C # Establecer colección?


488

¿Alguien sabe si hay un buen equivalente a la Setcolección de Java en C #? Sé que puedes imitar un conjunto usando a Dictionaryo a HashTablerellenando pero ignorando los valores, pero esa no es una forma muy elegante.

Respuestas:


142

Prueba HashSet :

La clase HashSet (Of T) proporciona operaciones de conjuntos de alto rendimiento. Un conjunto es una colección que no contiene elementos duplicados, y cuyos elementos no están en un orden particular ...

La capacidad de un objeto HashSet (Of T) es la cantidad de elementos que el objeto puede contener. La capacidad de un objeto HashSet (Of T) aumenta automáticamente a medida que se agregan elementos al objeto.

La clase HashSet (Of T) se basa en el modelo de conjuntos matemáticos y proporciona operaciones de conjuntos de alto rendimiento similares al acceso a las teclas de las colecciones Diccionario (Of TKey, TValue) o Hashtable . En términos simples, la clase HashSet (Of T) se puede considerar como una colección Dictionary (Of TKey, TValue) sin valores.

Una colección HashSet (Of T) no está ordenada y no puede contener elementos duplicados ...


8
Desafortunadamente, HashSets no se agregaron hasta hace poco. Si está trabajando en una versión anterior del marco, tendrá que seguir con su diccionario <> o Hashtable.
Greg D

413

Si está utilizando .NET 3.5, puede usarlo HashSet<T>. Sin embargo, es cierto que .NET no atiende conjuntos tan bien como Java.

Las Wintellect PowerCollections también pueden ayudar.


16
Sospecho que Set es una palabra clave en algunos idiomas, lo que podría causar problemas.
Jon Skeet

3
@Manish: No, no lo es. Consulte la sección 2.4.3 de la especificación C # 3. Solo tiene un significado especial para las propiedades.
Jon Skeet

28
La razón para llamarlo HashSet, en lugar de solo Set, es la misma que en Java: "Set" describe una interfaz, mientras que "HashSet" describe una implementación, específicamente, este es un Set respaldado por un Hash Map. De esta manera, sabemos (o deberíamos esperar) que la inserción y el acceso deberían tomar el tiempo de acceso O (1), en comparación con un "LinkedListSet" que nos llevaría a esperar que la inserción y el acceso tomaran el tiempo O (n).
David Souther

55
¿a qué te refieres con ".NET no atiende conjuntos tan bien como Java"? ¿Es este conjunto de alguna manera imperfecto en comparación con el de Java?
Louis Rhys

34
@Louis: ¿De qué conjunto estás hablando? Java tiene muchas implementaciones diferentes de Set para diversas situaciones. .NET tenía uno en .NET 3.5 (HashSet) y dos en .NET 4 (HashSet y SortedSet). El hecho de que tuvimos que esperar hasta .NET 3.5 para comenzar es bastante sorprendente.
Jon Skeet

26

Si está utilizando .NET 4.0 o posterior:

En el caso de que necesite ordenar, use SortedSet<T>. De lo contrario, si no lo hace, úselo HashSet<T>ya que es O(1)para operaciones de búsqueda y manipulación. Mientras que SortedSet<T>es O(log n)para buscar y manipular operaciones.



13

Utilizo un contenedor alrededor de un Dictionary<T, object>, almacenando nulos en los valores. Esto le da a O (1) agregar, buscar y eliminar en las teclas, y para todos los efectos, actúa como un conjunto.


2
Debe significar que es más o menos equivalente a std :: unordered_set. Se ordena std :: set. Por ejemplo, puede encontrar rápidamente el punto inicial y final de un rango e iterar desde el principio hasta el final, visitando los elementos en orden de teclas. SortedDictionary es más o menos equivalente a std :: set.
doug65536


-5

Sé que este es un hilo antiguo, pero me encontraba con el mismo problema y descubrí que HashSet era muy poco confiable porque, dado el mismo origen, GetHashCode () devolvió códigos diferentes. Entonces, pensé, ¿por qué no usar una Lista y ocultar el método de agregar como este?

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

Como List usa el método Equals únicamente para determinar la igualdad, puede definir el método Equals en su tipo T para asegurarse de obtener los resultados deseados.


13
La razón por la que no querría usar esto es porque List.Containses de O(n)complejidad, lo que significa que su Addmétodo ahora también se vuelve O(n)complejo. Asumiendo que la colección interna no necesita ser redimensionada, Addpara ambosList y HashMapdebe ser O(1)compleja. TLDR: Esto funcionará, pero es hacky y menos eficiente.
Richard Marskell - Drackir

66
Claro, si sus objetos no devuelven un valor apropiado para GetHashCode, no debe colocarlos en un contenedor basado en hash. Sería mejor arreglar GetHashCode que usar un contenedor menos eficiente.
bmm6o
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.