web-dev-qa-db-fra.com

Liste efficace de chaînes uniques C #

Quelle est la façon la plus efficace de stocker une liste de chaînes en ignorant les doublons? Je pensais qu'un dictionnaire pourrait mieux insérer des chaînes en écrivant dict [str] = false; et énumérer les clés sous forme de liste. Est-ce une bonne solution?

83
user34537

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.

105
JP Alioto

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);   
21
Perpetualcoder

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, je me suis compromis avec un HashSet et une List 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'a ajouté d'éléments à la liste, vous aurez un ensemble unique ordonné par insertion!

14
scone

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
Dave Hollingsworth

Utilisez HashSet, pas besoin de vérifier .Contains (), ajoutez simplement vos éléments dans la liste et si son doublon 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
8
Priyang

Cela ne fait pas partie de l'espace de noms du système mais a utilisé les Iesi.Collections de http://www.codeproject.com/KB/recipes/sets.aspx avec NHibernate. Il prend en charge l'ensemble haché ainsi que 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
AndrewB

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 tablea

Tester:

using FluentAssertions;

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

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

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

Test du code source (Gist)

2
Alexey Solonets