2009-01-18 7 views
63

Ich habe eine Liste von ElementenWie Dubletten mit LINQ in List Count

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

Ich möchte sie zurück in eine Liste wie das, 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 dies mit LINQ und C# tun können.

Dank Alle

EDIT 2 Angezeigt Code:

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 diese Ergebnisse:

  • 1 Hallo Welt mal
  • 1 Hallo Welt mal
  • 1 Hallo Welt.
  • 1 Hallo Welt mal
  • 1 Hallo Welt mal
  • 1 Hallo Welt mal
  • 1 Hallo Welt.
  • 1 Hallo Welt mal

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

Es zeigen soll:

  • 6 Hallo Weltzeit 234234
  • 2 Hallo Welt. 23432432
+0

Angesichts Ihrer Ergebnisse ist es offensichtlich, dass Programm behandelt alle Ihre Artikel als eigenständige - wie gesagt, Sie müssen benutzerdefinierte implementieren Vergleich, sonst ist es nicht möglich, verschiedene Werte zu wählen – aku

Antwort

87

Sie können "group by" + "orderby" 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 Reaktion auf this post (jetzt gelöscht):

Wenn Sie eine Liste mit einigen benutzerdefinierten Objekten haben, dann müssen Sie custom comparer oder eine Gruppe von bestimmten Eigenschaft verwenden.

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

auf dem neuesten Update Basierend:

Sie haben diese Codezeile:

group xx by xx into g 

Seit xx ist ein System, benutzerdefiniertes Objekt nicht weiß, wie man sich gegen ein anderes Element zu vergleichen. Wie ich bereits geschrieben habe, müssen Sie den Compiler führen und eine Eigenschaft bereitstellen, die beim Objektvergleich verwendet wird oder einen benutzerdefinierten Vergleich bereitstellt. Hier ein Beispiel:

Bitte beachte, dass ich Foo.Name als Schlüssel verwenden - das heißt Objekte basierend auf dem Wert von Namen Eigenschaft gruppiert werden.

Es gibt einen Haken - Sie behandeln 2 Objekte zu duplizieren basierend auf ihren Namen, aber was ist mit ID? In meinem Beispiel nehme ich einfach 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); 
} 
+0

nur die Ergebnisse zu einem benutzerdefinierten Repeater anzeigen .... –

+0

Scott, zeigen Sie einfach Ihren Code – aku

+0

Fertig, Sie können jetzt einen Einblick bekommen, was ich betrachte. –

36

Etwas kürzere Version mit Methoden Kette:

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

einfach zu verstehen und gut funktioniert –

+1

Definitiv die beste Lösung - danke! –

+0

Einfachheit mit Fachwissen. – Hitsa00

4

Die anderen Lösungen verwenden GroupBy. GroupBy ist langsam (es, alle Elemente im Speicher hält), so schrieb ich meine eigene Methode 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 diese

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

Sie auch Wörterbuch tun können: