C # Establecer colección?

¿Alguien sabe si hay un buen equivalente a la colección de Set de Java en C #? Sé que puedes imitar un conjunto usando un Dictionary o una HashTable al poblar, pero ignorando los valores, pero esa no es una manera muy elegante.

Pruebe HashSet :

La clase HashSet (Of T) proporciona operaciones de conjunto de alto rendimiento. Un conjunto es una colección que no contiene elementos duplicados, y cuyos elementos no están en ningún 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 conjunto de alto rendimiento similares al acceso a las claves de las colecciones Diccionario (de 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 …

Si usa .NET 3.5, puede usar HashSet . Es cierto que .NET no se ocupa de los conjuntos, así como tampoco lo hace Java.

Wintellect PowerCollections también puede ser útil.

La estructura de datos HashSet :

La estructura de datos HashSet Framework Class Library se introdujo en .NET Framework 3.5. Se puede encontrar una lista completa de sus miembros en la página de referencia de MSDN para HashSet .

HashSet está más o menos modelado después de un conjunto matemático , lo que significa que:

  1. Puede no contener valores duplicados.

  2. Sus elementos no están en un orden particular; por lo tanto, el tipo no implementa la interfaz IList , sino la ICollection más básica. Como consecuencia, los elementos dentro de un conjunto hash no se pueden acceder aleatoriamente a través de índices; solo pueden repetirse a través de un enumerador.

  3. Ciertas funciones de conjunto como Union , Intersection , IsSubsetOf , IsSupersetOf están disponibles. Estos pueden ser útiles cuando se trabaja con conjuntos múltiples.

Otra diferencia entre HashSet y List es que al invocar el método Add(item) un conjunto de hash se devuelve un valor booleano: true si el elemento se agregó y de lo contrario es false (porque ya se encontró en el conjunto).

¿Por qué no List ?

Dado que un HashSet es simplemente una colección de objetos únicos, puede preguntarse por qué tiene que ser una estructura de datos. Una List normal List podría tener el mismo comportamiento al verificar si un objeto se encuentra en la lista antes de agregarlo.

La respuesta corta es velocidad. La búsqueda a través de una List normal es muy lenta a medida que se agregan más elementos. Un HashSet requiere un diseño de estructura que permita una búsqueda rápida y velocidades de inserción.

Puntos de referencia:

Comparemos la velocidad de rendimiento de un HashSet contra un List .

Cada prueba consistió en sumr números enteros de 0 a 9.999 para cada colección. Sin embargo, el mod 25 se aplicó a cada número entero. Mod 25 crea los tipos máximos de elementos 25. Dado que se agregaron 10.000 elementos, esto obligó a 400 colisiones a ocurrir, dando a las estructuras de datos la oportunidad de utilizar sus algoritmos de búsqueda. Los tiempos se midieron 3 veces después de 10,000 ensayos y se promediaron.

No preste demasiada atención a los tiempos de ejecución específicos de las pruebas, ya que dependen de mi hardware, pero mire cómo se comparan entre sí.

  Average time [ms] ---------------------------- HashSet 2,290 List 5,505 

Ahora hagamos elementos objetos en lugar de tipos primitivos. Escribí una clase de Person rápida con tres campos: Name , LastName e ID . Como no incluí ninguna forma específica de comparar objetos, todos los elementos se agregarán sin colisiones. Esta vez, se agregaron 1,000 objetos Person a cada colección para una sola prueba. Se promediaron los tiempos totales de 3 series de 1,000 pruebas.

  Average time [ms] ---------------------------- HashSet 201 List 3,000 

Como puede ver, la diferencia en los tiempos de ejecución se vuelve astronómica cuando se usan objetos, lo que hace que el HashSet ventajoso.

Si usa .NET 4.0 o posterior:

En el caso en que necesite ordenar, utilice SortedSet . De lo contrario, si no lo hace, utilice HashSet ya que es O(1) para las operaciones de búsqueda y manipulación. Mientras que SortedSet es O(log n) para operaciones de búsqueda y manipulación.

Yo uso Iesi.Collections http://www.codeproject.com/KB/recipes/sets.aspx

Se usa en muchos proyectos de OSS. La encontré por primera vez en NHibernate.

Utilizo un contenedor alrededor de un Dictionary , 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.

Eche un vistazo a PowerCollections en CodePlex. Además de Set y OrderedSet, tiene algunos otros tipos de colecciones útiles como Deque, MultiDictionary, Bag, OrderedBag, OrderedDictionary y OrderedMultiDictionary.

Para obtener más colecciones, también está la Biblioteca de colecciones genéricas C5 .

Como otros han mencionado, no parece haber una implementación establecida en el estándar .NET con semántica establecida.

Consulte esta pregunta para HashSet por qué HashSet no siempre se desea como una implementación establecida.

Si estás interesado en rodar tu propia clase set, aquí hay un enfoque simple:

 public sealed class MathSet : HashSet, IEquatable> { public override int GetHashCode() => this.Select(elt => elt.GetHashCode()).Sum().GetHashCode(); public bool Equals(MathSet obj) => SetEquals(obj); public override bool Equals(object obj) => Equals(obj as MathSet); public static bool operator ==(MathSet a, MathSet b) => ReferenceEquals(a, null) ? ReferenceEquals(b, null) : a.Equals(b); public static bool operator !=(MathSet a, MathSet b) => !(a == b); } 

Ejemplo de uso:

 var a = new MathSet { 1, 2, 3 }; var b = new MathSet { 3, 2, 1 }; var c = a.Equals(b); // true var d = new MathSet> { a, b }; // contains one element var e = a == b; // true 

Puede implementar su propia implementación de conjunto viable en un par de horas. Usé esto cuando tuve que hacerlo (lo siento, no tengo el código a mano): http://java.sun.com/j2se/1.4.2/docs/api/java/util/Set.html

Sé que este es un hilo viejo, pero me encontré con el mismo problema y encontré que HashSet es muy poco confiable porque dado el mismo valor inicial, GetHashCode () devolvió códigos diferentes. Entonces, pensé, ¿por qué no solo usar una lista y ocultar el método de agregar como este

 public class UniqueList : List { 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.