127 votes

Comment trouver tous les doublons d'une Liste<string> ?

J'ai un List<string> qui a quelques mots en double. J'ai besoin de trouver tous les mots qui sont en double.

Un truc pour les avoir tous ?

225voto

Giuseppe Ottaviano Points 1638

Dans le cadre de .NET framework 3.5 et plus, vous pouvez utiliser Enumerable.GroupBy qui renvoie une énumération d'énumérations de clés dupliquées, puis filtre toutes les énumérations dont le nombre est <=1, puis sélectionne leurs clés pour revenir à une seule énumération :

var duplicateKeys = list.GroupBy(x => x)
                        .Where(group => group.Count() > 1)
                        .Select(group => group.Key);

36voto

ICR Points 6960

Si vous utilisez LINQ, vous pouvez utiliser la requête suivante :

var duplicateItems = from x in list
                     group x by x into grouped
                     where grouped.Count() > 1
                     select grouped.Key;

ou, si vous le préférez sans le sucre syntaxique :

var duplicateItems = list.GroupBy(x => x).Where(x => x.Count() > 1).Select(x => x.Key);

Cela permet de regrouper tous les éléments qui sont identiques, puis de filtrer uniquement les groupes contenant plus d'un élément. Enfin, elle ne sélectionne que la clé de ces groupes, car vous n'avez pas besoin du nombre.

Si vous préférez ne pas utiliser LINQ, vous pouvez utiliser cette méthode d'extension :

public void SomeMethod {
    var duplicateItems = list.GetDuplicates();
    …
}

public static IEnumerable<T> GetDuplicates<T>(this IEnumerable<T> source) {
    HashSet<T> itemsSeen = new HashSet<T>();
    HashSet<T> itemsYielded = new HashSet<T>();

    foreach (T item in source) {
        if (!itemsSeen.Add(item)) {
            if (itemsYielded.Add(item)) {
                yield return item;
            }
        }
    }
}

Il garde la trace des éléments qu'il a vus et rapportés. S'il n'a pas vu un objet auparavant, il l'ajoute à la liste des objets vus, sinon il l'ignore. S'il n'a pas cédé un objet auparavant, il le cède, sinon il l'ignore.

20voto

evilone Points 10400

Et sans le LINQ :

string[] ss = {"1","1","1"};

var myList = new List<string>();
var duplicates = new List<string>();

foreach (var s in ss)
{
   if (!myList.Contains(s))
      myList.Add(s);
   else
      duplicates.Add(s);
}

// show list without duplicates 
foreach (var s in myList)
   Console.WriteLine(s);

// show duplicates list
foreach (var s in duplicates)
   Console.WriteLine(s);

14voto

Si vous cherchez une méthode plus générique :

public static List<U> FindDuplicates<T, U>(this List<T> list, Func<T, U> keySelector)
    {
        return list.GroupBy(keySelector)
            .Where(group => group.Count() > 1)
            .Select(group => group.Key).ToList();
    }

EDIT : Voici un exemple :

public class Person {
    public string Name {get;set;}
    public int Age {get;set;}
}

List<Person> list = new List<Person>() { new Person() { Name = "John", Age = 22 }, new Person() { Name = "John", Age = 30 }, new Person() { Name = "Jack", Age = 30 } };

var duplicateNames = list.FindDuplicates(p => p.Name);
var duplicateAges = list.FindDuplicates(p => p.Age);

foreach(var dupName in duplicateNames) {
    Console.WriteLine(dupName); // Will print out John
}

foreach(var dupAge in duplicateAges) {
    Console.WriteLine(dupAge); // Will print out 30
}

5voto

Manish Basantani Points 4347

En utilisant LINQ, bien sûr. Le code ci-dessous vous donnerait le dictionnaire des éléments sous forme de chaîne, et le nombre de chaque élément dans votre liste de sources.

var item2ItemCount = list.GroupBy(item => item).ToDictionary(x=>x.Key,x=>x.Count());

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X