Liste efficace de chaînes uniques C #


86

Quel est le moyen le plus efficace de stocker une liste de chaînes en ignorant les doublons? Je pensais qu'un dictionnaire serait peut-être préférable d'insérer des chaînes en écrivant dict [str] = false; et énumérer à travers les clés sous forme de liste. Est-ce une bonne solution?

Réponses:


111

Si vous utilisez .NET 3.5, le HashSet devrait fonctionner pour vous.

La classe HashSet <(Of <(T>)>) fournit des opérations d'ensemble hautes performances. Un ensemble est une collection qui ne contient aucun élément en double et dont les éléments ne sont pas dans un ordre particulier.


5
Mais a HashSetperdra l'ordre des articles. Une fonctionnalité Listfournie.
aggsol

4
Supplémentaire: Il existe également SortedSet <T> qui est un HashSet trié pratique.
WhoIsRich

Notez également que HashSet n'est pas accessible via indice, uniquement via un énumérateur par opposition à une liste.
Andrew

23

Vous pouvez chercher à faire quelque chose comme ça

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
Vous n'avez pas besoin de la vérification Contains avec un HashSet. Vous pouvez simplement appeler la méthode Add directement et elle retournera vrai ou faux selon que l'élément existe déjà ou non.
LukeH

1
La réponse doit être modifiée pour supprimer l'appel aux Contains redondants. C'est tout ce dont vous avez besoin pour que l'exemple ci-dessus fonctionne: var collectionWithDup = new [] {"one", "one", "two", "one", "two", "zero"}; var uniqueValues ​​= new HashSet <chaîne> (collectionWithDup);
user3285954

14

Je ne sais pas si cela compte comme une bonne réponse, mais face à la nécessité d'un ensemble unique qui maintient l'ordre d'insertion, j'ai fait un compromis avec un HashSet et une liste côte à côte. Dans ce cas, chaque fois que vous ajoutez à l'ensemble, procédez comme suit:

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

Lorsque vous supprimez des éléments, assurez-vous de les supprimer des deux. Ainsi, tant que vous pouvez être sûr que rien d'autre n'ajoute d'éléments à la liste, vous aurez un ensemble unique commandé par insertion!


10

Vous pouvez également utiliser Linq comme dans:

using System.Linq;

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

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

8

Utilisez HashSet, pas besoin de vérifier .Contains (), ajoutez simplement vos éléments dans la liste et s'il est dupliqué, il ne l'ajoutera pas.

   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

Cela ne fait pas partie de l'espace de noms du système, mais a utilisé les collections Iesi.Collections de http://www.codeproject.com/KB/recipes/sets.aspx avec NHibernate. Il prend en charge l'ensemble haché avec l'ensemble trié, l'ensemble de dictionnaires, etc. Depuis qu'il a été utilisé avec NHibernate, il a été largement utilisé et très stable. Cela ne nécessite pas non plus .Net 3.5


2

Voici une autre solution sans utiliser le HashSet.

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

Il a été adopté à partir de ce fil: javascript - Valeurs uniques dans un tableau

Tester:

using FluentAssertions;

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

Test de performance pour List, HashSetet SortedSet. 1 million d'itérations:

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

Test du code source (gist)

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.