List<int>
Wie kann ich mit LINQ aus a eine Liste abrufen, die mehr als einmal wiederholte Einträge und deren Werte enthält?
List<int>
Wie kann ich mit LINQ aus a eine Liste abrufen, die mehr als einmal wiederholte Einträge und deren Werte enthält?
Antworten:
Der einfachste Weg, um das Problem zu lösen, besteht darin, die Elemente anhand ihres Werts zu gruppieren und dann einen Vertreter der Gruppe auszuwählen, wenn die Gruppe mehr als ein Element enthält. In LINQ bedeutet dies:
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();
Dies gibt List
einen anonymen Typ zurück, und jedes Element verfügt über die Eigenschaften Element
und Counter
, um die benötigten Informationen abzurufen.
Und wenn es sich um ein Wörterbuch handelt, das Sie suchen, können Sie es verwenden
var query = lst.GroupBy(x => x)
.Where(g => g.Count() > 1)
.ToDictionary(x => x.Key, y => y.Count());
Dies gibt ein Wörterbuch mit Ihrem Element als Schlüssel und der Häufigkeit zurück, mit der es als Wert wiederholt wird.
code
for (int i = 0; i <duplicates.Count; i ++) {int duplicate = duplicates [i]; duplicatesLocation.Add (duplizieren, neue Liste <int> ()); für (int k = 0; k <HitsList.Length; k ++) {if (HitsList [k]. Enthält (Duplikat)) {DuplikateLocation.ElementAt (i) .Value.Add (k); }} // entferne Duplikate nach einigen Regeln. }code
Finden Sie heraus, ob eine Aufzählung ein Duplikat enthält :
var anyDuplicate = enumerable.GroupBy(x => x.Key).Any(g => g.Count() > 1);
Finden Sie heraus, ob alle Werte in einer Aufzählung eindeutig sind :
var allUnique = enumerable.GroupBy(x => x.Key).All(g => g.Count() == 1);
Ein anderer Weg ist HashSet
:
var hash = new HashSet<int>();
var duplicates = list.Where(i => !hash.Add(i));
Wenn Sie eindeutige Werte in Ihrer Duplikatliste haben möchten:
var myhash = new HashSet<int>();
var mylist = new List<int>(){1,1,2,2,3,3,3,4,4,4};
var duplicates = mylist.Where(item => !myhash.Add(item)).Distinct().ToList();
Hier ist die gleiche Lösung wie bei einer generischen Erweiterungsmethode:
public static class Extensions
{
public static IEnumerable<TSource> GetDuplicates<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> selector, IEqualityComparer<TKey> comparer)
{
var hash = new HashSet<TKey>(comparer);
return source.Where(item => !hash.Add(selector(item))).ToList();
}
public static IEnumerable<TSource> GetDuplicates<TSource>(this IEnumerable<TSource> source, IEqualityComparer<TSource> comparer)
{
return source.GetDuplicates(x => x, comparer);
}
public static IEnumerable<TSource> GetDuplicates<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> selector)
{
return source.GetDuplicates(selector, null);
}
public static IEnumerable<TSource> GetDuplicates<TSource>(this IEnumerable<TSource> source)
{
return source.GetDuplicates(x => x, null);
}
}
List<int> { 1, 2, 3, 4, 5, 2 }
als Quelle ist das Ergebnis ein IEnumerable<int>
Element mit dem Wert 1
(wobei der korrekte doppelte Wert 2 ist)
Console.WriteLine("Count: {0}", duplicates.Count());
direkt darunter hinzugefügt und sie wird gedruckt 6
. Sofern mir nichts über die Anforderungen für diese Funktion fehlt, sollte die resultierende Sammlung nur 1 Element enthalten.
ToList
, um das Problem zu beheben, aber es bedeutet, dass die Methode ausgeführt wird, sobald sie aufgerufen wird, und nicht, wenn Sie die Ergebnisse durchlaufen.
var hash = new HashSet<int>();
var duplicates = list.Where(i => !hash.Add(i));
führt zu einer Liste, die alle Vorkommen von Duplikaten enthält. Wenn Sie also vier Vorkommen von 2 in Ihrer Liste haben, enthält Ihre doppelte Liste drei Vorkommen von 2, da nur eine der 2 zum HashSet hinzugefügt werden kann. Wenn Sie möchten, dass Ihre Liste eindeutige Werte für jedes Duplikat enthält, verwenden Sie stattdessen diesen Code:var duplicates = mylist.Where(item => !myhash.Add(item)).ToList().Distinct().ToList();
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<TSource> Duplicates<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> selector)
{
var grouped = source.GroupBy(selector);
var moreThan1 = grouped.Where(i => i.IsMultiple());
return moreThan1.SelectMany(i => i);
}
public static IEnumerable<TSource> Duplicates<TSource, TKey>(this IEnumerable<TSource> source)
{
return source.Duplicates(i => i);
}
public static bool IsMultiple<T>(this IEnumerable<T> source)
{
var enumerator = source.GetEnumerator();
return enumerator.MoveNext() && enumerator.MoveNext();
}
}
Die Verwendung von IsMultiple () in der Duplicates-Methode ist schneller als Count (), da hierdurch nicht die gesamte Auflistung iteriert wird.
Count()
ist vorbestellt berechnet und Ihre Lösung ist wahrscheinlich langsamer.
Count()
] unterscheidet sich also grundlegend vom Iterieren der gesamten Liste. Count()
ist vorberechnet, die gesamte Liste jedoch nicht.
Ich habe eine Erweiterung erstellt, um darauf zu antworten, dass Sie sie in Ihre Projekte aufnehmen können. Ich denke, dies ist der häufigste Fall, wenn Sie in List oder Linq nach Duplikaten 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<T> getMoreThanOnceRepeated<T>(this IEnumerable<T> extList, Func<T, object> 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<T> getAllRepeated<T>(this IEnumerable<T> extList, Func<T, object> 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<Person> PersonsLst = new List<Person>(){
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
*/
}
So finden Sie nur die doppelten Werte:
var duplicates = list.GroupBy(x => x.Key).Any(g => g.Count() > 1);
Z.B. var list = new [] {1,2,3,1,4,2};
Gruppieren nach gruppiert also die Zahlen nach ihren Schlüsseln und behält die Anzahl (Anzahl der Wiederholungen) bei. Danach überprüfen wir nur die Werte, die sich mehr als einmal wiederholt haben.
So finden Sie nur die eindeutigen Werte:
var unique = list.GroupBy(x => x.Key).All(g => g.Count() == 1);
Z.B. var list = new [] {1,2,3,1,4,2};
Gruppieren nach gruppiert also die Zahlen nach ihren Schlüsseln und behält die Anzahl (Anzahl der Wiederholungen) bei. Danach überprüfen wir nur noch, ob die Werte, die sich nur einmal wiederholt haben, eindeutig sind.
var unique = list.Distinct(x => x)
Vollständiger Satz von Linq to SQL-Erweiterungen von Duplikatfunktionen, die in MS SQL Server überprüft wurden. Ohne Verwendung von .ToList () oder IEnumerable. Diese Abfragen werden in SQL Server und nicht im Speicher ausgeführt. . Die Ergebnisse werden nur im Speicher zurückgegeben.
public static class Linq2SqlExtensions {
public class CountOfT<T> {
public T Key { get; set; }
public int Count { get; set; }
}
public static IQueryable<TKey> Duplicates<TSource, TKey>(this IQueryable<TSource> source, Expression<Func<TSource, TKey>> groupBy)
=> source.GroupBy(groupBy).Where(w => w.Count() > 1).Select(s => s.Key);
public static IQueryable<TSource> GetDuplicates<TSource, TKey>(this IQueryable<TSource> source, Expression<Func<TSource, TKey>> groupBy)
=> source.GroupBy(groupBy).Where(w => w.Count() > 1).SelectMany(s => s);
public static IQueryable<CountOfT<TKey>> DuplicatesCounts<TSource, TKey>(this IQueryable<TSource> source, Expression<Func<TSource, TKey>> groupBy)
=> source.GroupBy(groupBy).Where(w => w.Count() > 1).Select(y => new CountOfT<TKey> { Key = y.Key, Count = y.Count() });
public static IQueryable<Tuple<TKey, int>> DuplicatesCountsAsTuble<TSource, TKey>(this IQueryable<TSource> source, Expression<Func<TSource, TKey>> groupBy)
=> source.GroupBy(groupBy).Where(w => w.Count() > 1).Select(s => Tuple.Create(s.Key, s.Count()));
}
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 ist in dieser Situation so.
var duplicates = model.list
.GroupBy(s => s.SAME_ID)
.Where(g => g.Count() > 1).Count() > 0;
if(duplicates) {
doSomething();
}