Lista eficiente de strings exclusivas C #


86

Qual é a maneira mais eficiente de armazenar uma lista de strings ignorando quaisquer duplicatas? Eu estava pensando que um dicionário pode ser melhor inserir strings escrevendo dict [str] = false; e enumerando por meio das chaves como uma lista. Essa é uma boa solução?

Respostas:


111

Se você estiver usando .NET 3.5, o HashSet deve funcionar para você.

A classe HashSet <(Of <(T>)>) fornece operações de conjunto de alto desempenho. Um conjunto é uma coleção que não contém elementos duplicados e cujos elementos não estão em uma ordem específica.


5
Mas um HashSetperderá a ordem dos itens. Um recurso que a Listfornece.
aggsol

4
Adicional: há também SortedSet <T>, que é um HashSet classificado conveniente.
WhoIsRich

Observe também que o HashSet não pode ser acessado por meio de índice, apenas por meio de um enumerador em oposição a uma Lista.
Andrew

23

Você pode tentar fazer algo assim

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
Você não precisa da verificação Contains com um HashSet. Você pode simplesmente chamar o método Add diretamente e ele retornará verdadeiro ou falso, dependendo se o item já existe ou não.
LukeH

1
A resposta deve ser editada para remover a chamada para Contém redundante. Isso é tudo que você precisa para o exemplo acima funcionar: var collectionWithDup = new [] {"um", "um", "dois", "um", "dois", "zero"}; var uniqueValues ​​= new HashSet <string> (collectionWithDup);
user3285954

14

Não tenho certeza se isso conta como uma boa resposta, mas quando confrontado com a necessidade de um conjunto exclusivo que mantenha a ordem de inserção, me comprometi com um HashSet e uma Lista lado a lado. Nesse caso, sempre que você adicionar ao conjunto, faça o seguinte:

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

Ao remover itens, certifique-se de removê-los de ambos. Assim, contanto que você tenha certeza de que nada mais adicionou itens à lista, você terá um conjunto exclusivo de ordem de inserção!


10

Você também pode usar o Linq como em:

using System.Linq;

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

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

8

Use o HashSet, não precisa marcar .Contains (), basta adicionar seus itens na lista e se estiver duplicado não irá adicioná-lo.

   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

Isso não faz parte do namespace do sistema, mas usei o Iesi.Collections de http://www.codeproject.com/KB/recipes/sets.aspx com NHibernate. Ele tem suporte para conjunto de hash junto com conjunto classificado, conjunto de dicionário e assim por diante. Desde que foi usado com NHibernate, tem sido usado extensivamente e muito estável. Isso também não requer .Net 3.5


2

Aqui está outra solução sem usar o HashSet.

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

Foi adotado a partir deste tópico: javascript - Valores únicos em uma matriz

Teste:

using FluentAssertions;

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

Teste de desempenho para List, HashSete SortedSet. 1 milhão de iterações:

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

Teste o código-fonte (essência)

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.