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 ?
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 ?
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);
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.
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);
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
}
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.