Wie kann ich unter Verwendung von LINQ aus einer List
eine Liste abrufen, die Einträge enthält, die mehr als einmal wiederholt werden, sowie ihre Werte?
Antworten
Zu viele Anzeigen?Ich habe eine Erweiterung erstellt, um darauf zu antworten. Du könntest sie in deinen Projekten verwenden, ich denke, dass sie in den meisten Fällen zurückgibt, wenn du nach Duplikaten in einer Liste oder Linq suchst.
Beispiel:
//Dummy-Klasse zum Vergleichen in der Liste
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;
}
}
//Die statische Erweiterungsklasse
public static class Extention
{
public static IEnumerable getMoreThanOnceRepeated(this IEnumerable extList, Func groupProps) where T : class
{ //Gibt nur die zweite und alle weiteren Wiederholungen zurück
return extList
.GroupBy(groupProps)
.SelectMany(z => z.Skip(1)); //Überspringt das erste Vorkommen und gibt alle weiteren zurück, die wiederholen
}
public static IEnumerable getAllRepeated(this IEnumerable extList, Func groupProps) where T : class
{
//Alle Zeilen abrufen, die wiederholen
return extList
.GroupBy(groupProps)
.Where(z => z.Count() > 1) //Nur die unterschiedlichen filtern
.SelectMany(z => z);//Alles in "where" muss zurückgegeben werden
}
}
//wie man es benutzt:
void DuplicateExample()
{
//Liste bevölkern
List PersonsLst = new List(){
new Person(1,"Ricardo","Figueiredo"), //erstes Duplikat zum Beispiel
new Person(2,"Ana","Figueiredo"),
new Person(3,"Ricardo","Figueiredo"),//zweites Duplikat zum Beispiel
new Person(4,"Margarida","Figueiredo"),
new Person(5,"Ricardo","Figueiredo")//drittes Duplikat zum Beispiel
};
Console.WriteLine("Alle:");
PersonsLst.ForEach(z => Console.WriteLine("{0} -> {1} {2}", z.Id, z.Name, z.Surname));
/* AUSGABE:
Alle:
1 -> Ricardo Figueiredo
2 -> Ana Figueiredo
3 -> Ricardo Figueiredo
4 -> Margarida Figueiredo
5 -> Ricardo Figueiredo
*/
Console.WriteLine("Alle Zeilen mit wiederholten Daten");
PersonsLst.getAllRepeated(z => new { z.Name, z.Surname })
.ToList()
.ForEach(z => Console.WriteLine("{0} -> {1} {2}", z.Id, z.Name, z.Surname));
/* AUSGABE:
Alle Zeilen mit wiederholten Daten
1 -> Ricardo Figueiredo
3 -> Ricardo Figueiredo
5 -> Ricardo Figueiredo
*/
Console.WriteLine("Nur mehrfach wiederholt");
PersonsLst.getMoreThanOnceRepeated(z => new { z.Name, z.Surname })
.ToList()
.ForEach(z => Console.WriteLine("{0} -> {1} {2}", z.Id, z.Name, z.Surname));
/* AUSGABE:
Nur mehrfach wiederholt
3 -> Ricardo Figueiredo
5 -> Ricardo Figueiredo
*/
}
Es gibt eine Antwort, aber ich habe nicht verstanden, warum es nicht funktioniert;
var anyDuplicate = enumerable.GroupBy(x => x.Key).Any(g => g.Count() > 1);
Meine Lösung sieht in dieser Situation so aus;
var duplicates = model.list
.GroupBy(s => s.SAME_ID)
.Where(g => g.Count() > 1).Count() > 0;
if(duplicates) {
doSomething();
}
Komplettes Set von Linq-to-SQL-Erweiterungen der Duplikatsfunktionen, die in MS SQL Server überprüft wurden. Ohne die Verwendung von .ToList() oder IEnumerable. Diese Abfragen werden im SQL Server ausgeführt anstatt im Speicher. Die Ergebnisse werden nur im Speicher zurückgegeben.
public static class Linq2SqlExtensions {
public class CountOfT {
public T Key { get; set; }
public int Count { get; set; }
}
public static IQueryable Duplicates(this IQueryable source, Expression> groupBy)
=> source.GroupBy(groupBy).Where(w => w.Count() > 1).Select(s => s.Key);
public static IQueryable GetDuplicates(this IQueryable source, Expression> groupBy)
=> source.GroupBy(groupBy).Where(w => w.Count() > 1).SelectMany(s => s);
public static IQueryable> DuplicatesCounts(this IQueryable source, Expression> groupBy)
=> source.GroupBy(groupBy).Where(w => w.Count() > 1).Select(y => new CountOfT { Key = y.Key, Count = y.Count() });
public static IQueryable> DuplicatesCountsAsTuble(this IQueryable source, Expression> groupBy)
=> source.GroupBy(groupBy).Where(w => w.Count() > 1).Select(s => Tuple.Create(s.Key, s.Count()));
}