it-swarm.com.de

C # LINQ sucht nach Duplikaten in der Liste

Wie kann ich mit LINQ von einem List<int> aus eine Liste abrufen, die mehrmals wiederholte Einträge und deren Werte enthält?

233
Mirko Arcese

Der einfachste Weg, das Problem zu lösen, besteht darin, die Elemente nach ihrem Wert zu gruppieren und dann einen Vertreter der Gruppe auszuwählen, wenn sich mehrere Elemente in der Gruppe befinden. 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 sich die Elemente wiederholen, 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. Jedes Element verfügt über die Eigenschaften Element und Counter, um die benötigten Informationen abzurufen.

Und wenn Sie nach einem Wörterbuch suchen, können Sie es 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.

414
Save

Finden Sie heraus, ob ein Aufzählungszeichen ein beliebiges Duplikat enthält:

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

Finden Sie heraus, ob alle / Werte in einem Aufzählungszeichen eindeutig sind :

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

Eine andere Möglichkeit ist HashSet:

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

Wenn Sie eindeutige Werte in Ihrer Duplikatenliste wünschen:

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)).ToList().Distinct().ToList();

Hier ist die gleiche Lösung wie eine generische 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);
  }
}
18
HuBeZa

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 dadurch nicht die gesamte Auflistung durchlaufen wird.

10
Alex Siepman

Ich habe eine Erweiterung erstellt, um darauf zu antworten, dass Sie sie in Ihre Projekte aufnehmen könnten. Ich denke, dass dies der Fall ist, 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
        */
}
6

Vollständiger Satz von Linq-zu-SQL-Erweiterungen von Duplicates-Funktionen, die in MS SQL Server geprüft wurden. Ohne .ToList () oder IEnumerable zu verwenden. Diese Abfragen werden in SQL Server und nicht im Arbeitsspeicher ausgeführt. . Die Ergebnisse kehren nur im Speicher zurück.

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()));
}
1
GeoB

Um nur die doppelten Werte zu finden:

var duplicates = list.GroupBy(x => x.Key).Any(g => g.Count() > 1);

ZB . Var list = new [] {1,2,3,1,4,2};

so gruppieren nach gruppiert 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.

Um nur die uniuqe-Werte zu finden:

var unique = list.GroupBy(x => x.Key).All(g => g.Count() == 1);

ZB . Var list = new [] {1,2,3,1,4,2};

so gruppieren nach gruppiert die Zahlen nach ihren Schlüsseln und behält die Anzahl (Anzahl der Wiederholungen) bei. Danach überprüfen wir nur die Werte, die sich nur einmal wiederholt haben, um eindeutig zu sein.

1
LAV VISHWAKARMA