So zählen Sie Duplikate in einer Liste mit LINQ


75

Ich habe eine Liste von Gegenständen

  • John ID
  • Matt ID
  • John ID
  • Scott ID
  • Matt ID
  • John ID
  • Lucas ID

Ich möchte sie wieder in eine Liste wie diese verschieben, was auch bedeutet, dass ich nach der höchsten Anzahl von Duplikaten sortieren möchte.

  • John ID 3
  • Matt ID 2
  • Scott ID 1
  • Lucas ID 1

Lassen Sie mich wissen, wie ich das mit LINQ und C # machen kann.

Vielen Dank an alle

EDIT 2 Code anzeigen:

    List<game> inventory = new List<game>();
    drinkingforDataContext db = new drinkingforDataContext();
    foreach (string item in tbTitle.Text.Split(' '))
    {

        List<game> getItems = (from dfg in db.drinkingfor_Games
                               where dfg.game_Name.Contains(tbTitle.Text)
                               select new game
                               {
                                   gameName = dfg.game_Name,
                                   gameID = Boomers.Utilities.Guids.Encoder.EncodeURLs(dfg.uid)
                               }).ToList<game>();

        for (int i = 0; i < getItems.Count(); i++)
        {
            inventory.Add(getItems[i]);
        }
    }

    var items = (from xx in inventory
                 group xx by xx into g
                 let count = g.Count()
                 orderby count descending
                 select new
                    {
                        Count = count,
                        gameName = g.Key.gameName,
                        gameID = g.Key.gameID
                    });

    lvRelatedGames.DataSource = items;
    lvRelatedGames.DataBind();

Diese Abfrage zeigt die folgenden Ergebnisse an:

  • 1 Hallo Weltzeit
  • 1 Hallo Weltzeit
  • 1 Hallo Welt.
  • 1 Hallo Weltzeit
  • 1 Hallo Weltzeit
  • 1 Hallo Weltzeit
  • 1 Hallo Welt.
  • 1 Hallo Weltzeit

Es gibt mir die Anzahl und den Namen, aber es gibt mir nicht die ID des Spiels ...

Es sollte Folgendes anzeigen:

  • 6 hallo welt mal 234234
  • 2 Hallo Welt. 23432432

Angesichts Ihrer Ergebnisse ist es offensichtlich, dass das Programm alle Ihre Elemente als unterschiedlich behandelt - wie gesagt, Sie müssen einen benutzerdefinierten Vergleicher implementieren, da es sonst nicht möglich ist, unterschiedliche Werte auszuwählen
aku

Antworten:


105

Sie können "Gruppieren nach" + "Bestellen nach" verwenden. Siehe LINQ 101 für Details

var list = new List<string> {"a", "b", "a", "c", "a", "b"};
var q = from x in list
        group x by x into g
        let count = g.Count()
        orderby count descending
        select new {Value = g.Key, Count = count};
foreach (var x in q)
{
    Console.WriteLine("Value: " + x.Value + " Count: " + x.Count);
}

Als Antwort auf diesen Beitrag (jetzt gelöscht):

Wenn Sie eine Liste einiger benutzerdefinierter Objekte haben, müssen Sie einen benutzerdefinierten Vergleicher verwenden oder nach bestimmten Eigenschaften gruppieren.

Auch die Abfrage kann kein Ergebnis anzeigen. Zeigen Sie uns den vollständigen Code, um eine bessere Hilfe zu erhalten.

Basierend auf Ihrem neuesten Update:

Sie haben diese Codezeile:

group xx by xx into g

Da xx ein benutzerdefiniertes Objektsystem ist, kann ein Element nicht mit einem anderen verglichen werden. Wie ich bereits geschrieben habe, müssen Sie den Compiler anleiten und einige Eigenschaften bereitstellen, die für den Objektvergleich verwendet werden, oder einen benutzerdefinierten Vergleicher bereitstellen. Hier ist ein Beispiel:

Beachten Sie, dass ich Foo.Name als Schlüssel verwende - dh Objekte werden basierend auf dem Wert der Name- Eigenschaft gruppiert .

Es gibt einen Haken: Sie behandeln 2 Objekte aufgrund ihrer Namen als dupliziert, aber was ist mit der ID? In meinem Beispiel nehme ich nur die ID des ersten Objekts in einer Gruppe. Wenn Ihre Objekte unterschiedliche IDs haben, kann dies ein Problem sein.

//Using extension methods
var q = list.GroupBy(x => x.Name)
            .Select(x => new {Count = x.Count(), 
                              Name = x.Key, 
                              ID = x.First().ID})
            .OrderByDescending(x => x.Count);

//Using LINQ
var q = from x in list
        group x by x.Name into g
        let count = g.Count()
        orderby count descending
        select new {Name = g.Key, Count = count, ID = g.First().ID};

foreach (var x in q)
{
    Console.WriteLine("Count: " + x.Count + " Name: " + x.Name + " ID: " + x.ID);
}

Fertig, Sie können jetzt einen Blick darauf werfen, was ich sehe.
SpoiledTechie.com

neue auswählen {Name = g.Key, Count = count, ID = g.First (). ID}; Dies war die Linie, die es funktioniert hat. Danke Aku. Es ist der .First.ID-Teil, der es zum Laufen gebracht hat. Ur Brilliant ...
SpoiledTechie.com

Danke für die x.First().IDSache
ParPar

50

Etwas kürzere Version mit Methodenkette:

var list = new List<string> {"a", "b", "a", "c", "a", "b"};
var q = list.GroupBy(x => x)
            .Select(g => new {Value = g.Key, Count = g.Count()})
            .OrderByDescending(x=>x.Count);

foreach (var x in q)
{
    Console.WriteLine("Value: " + x.Value + " Count: " + x.Count);
}

Einfachheit mit Fachwissen.
Hitsa

9

Sie können auch Wörterbuch machen:

 var list = new List<string> { "a", "b", "a", "c", "a", "b" };
 var result = list.GroupBy(x => x)
            .ToDictionary(y=>y.Key, y=>y.Count())
            .OrderByDescending(z => z.Value);

 foreach (var x in result)
        {
            Console.WriteLine("Value: " + x.Key + " Count: " + x.Value);
        }

6

Die anderen Lösungen verwenden GroupBy. GroupByist langsam (es enthält alle Elemente im Speicher), also habe ich meine eigene Methode geschrieben CountBy:

public static Dictionary<TKey,int> CountBy<TSource,TKey>(this IEnumerable<TSource> source, Func<TSource,TKey> keySelector)
{
    var countsByKey = new Dictionary<TKey,int>();
    foreach(var x in source)
    {
        var key = keySelector(x);
        if (!countsByKey.ContainsKey(key))
            countsByKey[key] = 0;
        countsByKey[key] += 1;
    }
    return countsByKey;
}

0

Hier ist das komplette Programm, bitte überprüfen Sie dies

static void Main(string[] args)
{
    List<string> li = new List<string>();
    li.Add("Ram");
    li.Add("shyam");
    li.Add("Ram");
    li.Add("Kumar");
    li.Add("Kumar");

    var x = from obj in li group obj by obj into g select new { Name = g.Key, Duplicatecount = g.Count() };
    foreach(var m in x)
    {
        Console.WriteLine(m.Name + "--" + m.Duplicatecount);
    }
    Console.ReadLine();
}        
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.