Lista eficiente de cadenas únicas C #


86

¿Cuál es la forma más eficaz de almacenar una lista de cadenas ignorando los duplicados? Estaba pensando que un diccionario puede ser mejor insertando cadenas escribiendo dict [str] = false; y enumerando las claves como una lista. ¿Es una buena solución?

Respuestas:


111

Si está utilizando .NET 3.5, HashSet debería funcionar para usted.

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.


5
Pero HashSetperderá el orden de los artículos. Una característica que Listproporciona.
aggsol

4
Adicional: También hay SortedSet <T>, que es un HashSet ordenado conveniente.
WhoIsRich

También tenga en cuenta que no se puede acceder a HashSet a través del índice, solo a través de un enumerador en oposición a una Lista.
Andrew

23

Puedes buscar hacer algo como esto

var hash = new HashSet<string>();
var collectionWithDup = new []{"one","one","two","one","two","zero"}; 

// No need to check for duplicates as the Add method
// will only add it if it doesn't exist already
foreach (var str in collectionWithDup)
    hash.Add(str);   

33
No necesita la verificación Contiene con un HashSet. Puede simplemente llamar al método Add directamente y devolverá verdadero o falso dependiendo de si el elemento ya existe o no.
LukeH

1
La respuesta debe editarse para eliminar la llamada a Contiene redundante. Esto es todo lo que necesita para que funcione el ejemplo anterior: var collectionWithDup = new [] {"uno", "uno", "dos", "uno", "dos", "cero"}; var uniqueValues ​​= new HashSet <cadena> (colecciónConDup);
user3285954

14

No estoy seguro de si esto cuenta como una buena respuesta, pero cuando me enfrenté a la necesidad de un conjunto único que mantuviera el orden de inserción, me comprometí con un HashSet y una Lista uno al lado del otro. En este caso, siempre que agregue al conjunto, haga lo siguiente:

if(hashSet.Add(item))
    orderList.Add(item);

Al quitar elementos, asegúrese de quitarlos de ambos. Por lo tanto, siempre que pueda estar seguro de que nada más agregó elementos a la lista, ¡tendrá un conjunto único ordenado por inserción!


10

También puede usar Linq como en:

using System.Linq;

var items = new List<string>() { "one", "one", "two", "one", "two", "zero" };

List<string> distinctItems = items.Distinct().ToList();

8

Use HashSet, no es necesario verificar .Contains (), simplemente agregue sus elementos en la lista y si está duplicado, no lo agregará.

   HashSet<int> uniqueList = new HashSet<int>();
   uniqueList.Add(1); // List has values 1
   uniqueList.Add(2);  // List has values 1,2
   uniqueList.Add(1);  // List has values 1,2
   Console.WriteLine(uniqueList.Count); // it will return 2

2

Esto no es parte del espacio de nombres del sistema, pero ha utilizado las colecciones Iesi.Collections de http://www.codeproject.com/KB/recipes/sets.aspx con NHibernate. Tiene soporte para conjuntos hash junto con conjuntos ordenados, conjuntos de diccionarios, etc. Desde que se ha utilizado con NHibernate se ha utilizado de forma extensiva y muy estable. Esto tampoco requiere .Net 3.5


2

Aquí hay otra solución sin usar HashSet.

var items = new List<string>() { "one", "one", "two", "one", "two", "zero" };
var uniqueItems = items.Where((item, index) => items.IndexOf(item) == index);

Fue adoptado de este hilo: javascript - Valores únicos en una matriz

Prueba:

using FluentAssertions;

uniqueItems.Count().Should().Be(3);
uniqueItems.Should().BeEquivalentTo("one", "two", "zero");

Prueba de rendimiento para List, HashSety SortedSet. 1 millón de iteraciones:

List: 564 ms
HashSet: 487 ms
SortedSet: 1932 ms

Probar código fuente (esencia)

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.