C # LINQ findet Duplikate in Liste

Wie kann ich mit LINQ aus einer List eine Liste abrufen, die mehrfach wiederholte Einträge und deren Werte enthält?

Der einfachste Weg zur Lösung des Problems besteht darin, die Elemente basierend auf ihrem Wert zu gruppieren und dann einen Vertreter der Gruppe auszuwählen, wenn mehr als ein Element in der Gruppe vorhanden ist. In LINQ bedeutet das:

 var query = lst.GroupBy(x => x) .Where(g => g.Count() > 1) .Select(y => y.Key) .ToList(); 

Wenn Sie wissen möchten, wie oft die Elemente wiederholt werden, können Sie Folgendes verwenden:

 var query = lst.GroupBy(x => x) .Where(g => g.Count() > 1) .Select(y => new { Element = y.Key, Counter = y.Count() }) .ToList(); 

Dadurch wird eine List eines anonymen Typs zurückgegeben, und jedes Element verfügt über die Eigenschaften Element und Counter , um die benötigten Informationen abzurufen.

Und schließlich, wenn es ein Wörterbuch ist, das Sie suchen, können Sie verwenden

 var query = lst.GroupBy(x => x) .Where(g => g.Count() > 1) .ToDictionary(x => x.Key, y => y.Count()); 

Dadurch wird ein Wörterbuch mit Ihrem Element als Schlüssel und der Anzahl der Wiederholungen als Wert zurückgegeben.

Finden Sie heraus, ob ein Enumerable ein Duplikat enthält:

 var anyDuplicate = enumerable.GroupBy(x => x.Key).Any(g => g.Count() > 1); 

Finden Sie heraus, ob alle Werte in einem Enumerable eindeutig sind :

 var allUnique = enumerable.GroupBy(x => x.Key).All(g => g.Count() == 1); 

Eine andere Möglichkeit ist die Verwendung von HashSet :

 var hash = new HashSet(); var duplicates = list.Where(i => !hash.Add(i)); 

Wenn Sie in Ihrer Duplikatsliste eindeutige Werte wünschen:

 var myhash = new HashSet(); var mylist = new List(){1,1,2,2,3,3,3,4,4,4}; var duplicates = mylist.Where(item => !myhash.Add(item)).ToList().Distinct().ToList(); 

Hier ist die gleiche Lösung wie eine generische Erweiterungsmethode:

 public static class Extensions { public static IEnumerable GetDuplicates(this IEnumerable source, Func selector, IEqualityComparer comparer) { var hash = new HashSet(comparer); return source.Where(item => !hash.Add(selector(item))).ToList(); } public static IEnumerable GetDuplicates(this IEnumerable source, IEqualityComparer comparer) { return source.GetDuplicates(x => x, comparer); } public static IEnumerable GetDuplicates(this IEnumerable source, Func selector) { return source.GetDuplicates(selector, null); } public static IEnumerable GetDuplicates(this IEnumerable source) { return source.GetDuplicates(x => x, null); } } 

Du kannst das:

 var list = new[] {1,2,3,1,4,2}; var duplicateItems = list.Duplicates(); 

Mit diesen Erweiterungsmethoden:

 public static class Extensions { public static IEnumerable Duplicates(this IEnumerable source, Func selector) { var grouped = source.GroupBy(selector); var moreThan1 = grouped.Where(i => i.IsMultiple()); return moreThan1.SelectMany(i => i); } public static IEnumerable Duplicates(this IEnumerable source) { return source.Duplicates(i => i); } public static bool IsMultiple(this IEnumerable source) { var enumerator = source.GetEnumerator(); return enumerator.MoveNext() && enumerator.MoveNext(); } } 

Die Verwendung von IsMultiple () in der Duplicates-Methode ist schneller als Count (), da dies nicht die gesamte Auflistung iteriert.

Ich habe eine Erweiterung erstellt, um darauf zu antworten, dass Sie es in Ihre Projekte aufnehmen könnten. Ich denke, dass dies den meisten Fall ergibt, wenn Sie nach Duplikaten in List oder Linq suchen.

Beispiel:

 //Dummy class to compare in list public class Person { public int Id { get; set; } public string Name { get; set; } public string Surname { get; set; } public Person(int id, string name, string surname) { this.Id = id; this.Name = name; this.Surname = surname; } } //The extention static class public static class Extention { public static IEnumerable getMoreThanOnceRepeated(this IEnumerable extList, Func groupProps) where T : class { //Return only the second and next reptition return extList .GroupBy(groupProps) .SelectMany(z => z.Skip(1)); //Skip the first occur and return all the others that repeats } public static IEnumerable getAllRepeated(this IEnumerable extList, Func groupProps) where T : class { //Get All the lines that has repeating return extList .GroupBy(groupProps) .Where(z => z.Count() > 1) //Filter only the distinct one .SelectMany(z => z);//All in where has to be retuned } } //how to use it: void DuplicateExample() { //Populate List List PersonsLst = new List(){ new Person(1,"Ricardo","Figueiredo"), //fist Duplicate to the example new Person(2,"Ana","Figueiredo"), new Person(3,"Ricardo","Figueiredo"),//second Duplicate to the example new Person(4,"Margarida","Figueiredo"), new Person(5,"Ricardo","Figueiredo")//third Duplicate to the example }; Console.WriteLine("All:"); PersonsLst.ForEach(z => Console.WriteLine("{0} -> {1} {2}", z.Id, z.Name, z.Surname)); /* OUTPUT: All: 1 -> Ricardo Figueiredo 2 -> Ana Figueiredo 3 -> Ricardo Figueiredo 4 -> Margarida Figueiredo 5 -> Ricardo Figueiredo */ Console.WriteLine("All lines with repeated data"); PersonsLst.getAllRepeated(z => new { z.Name, z.Surname }) .ToList() .ForEach(z => Console.WriteLine("{0} -> {1} {2}", z.Id, z.Name, z.Surname)); /* OUTPUT: All lines with repeated data 1 -> Ricardo Figueiredo 3 -> Ricardo Figueiredo 5 -> Ricardo Figueiredo */ Console.WriteLine("Only Repeated more than once"); PersonsLst.getMoreThanOnceRepeated(z => new { z.Name, z.Surname }) .ToList() .ForEach(z => Console.WriteLine("{0} -> {1} {2}", z.Id, z.Name, z.Surname)); /* OUTPUT: Only Repeated more than once 3 -> Ricardo Figueiredo 5 -> Ricardo Figueiredo */ } 

Kompletter Satz von Linq-Erweiterungen von [Duplicates] mit eingechecktem MS SQL Server

 public static class LinqExtensions { public class CounterOfT { public T Key { get; set; } public int Count { get; set; } } public static IQueryable Duplicates(this IEnumerable source, Func groupBy) where TSource : class => source.GroupBy(groupBy).Where(w => w.Count() > 1).Select(s => s.Key).AsQueryable(); public static IQueryable GetDuplicates(this IEnumerable source, Func groupBy) where TSource : class => source.GroupBy(groupBy).Where(w => w.Count() > 1).SelectMany(s => s).AsQueryable(); public static IQueryable> DuplicatesCounts(this IEnumerable source, Func groupBy) where TSource : class => source.GroupBy(groupBy).Where(w => w.Count() > 1).Select(y => new CounterOfT { Key = y.Key, Count = y.Count() }).AsQueryable(); public static IQueryable> DuplicatesCountsAsTuble(this IEnumerable source, Func groupBy) where TSource : class => source.GroupBy(groupBy).Where(w => w.Count() > 1).Select(s => Tuple.Create(s.Key, s.Count())).AsQueryable(); }