2009-01-18 62 views
63

計數重複的名單上有一個項目列表如何使用LINQ

  • 約翰ID
  • 馬特ID
  • 約翰ID
  • 斯科特ID
  • 馬特ID
  • 約翰·ID
  • 盧卡斯ID

我想把它們推回到這樣的列表中,這也意味着我想按最大數量的重複進行排序。

  • 約翰·ID 3
  • 馬特ID 2
  • 斯科特ID 1
  • 盧卡斯ID 1

讓我知道我可以使用LINQ和C#這樣做。

感謝所有

EDIT 2顯示代碼:

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

此查詢顯示這些結果:

  • 1的hello world次
  • 1的hello world次
  • 1 Hello World。
  • 1的hello world次
  • 1的hello world次
  • 1的hello world次
  • 1的Hello World。
  • 1的hello world次

它給我的數量和名稱,但它並沒有給我的遊戲ID ....

它應該顯示:

  • 6 hello world times 234234
  • 2 Hello World。 23432432
+0

給出你的結果很明顯,程序將所有的項目視爲不同的 - 正如我所說的,你需要實現自定義比較器,否則不可能選擇不同的值 – aku 2009-01-18 04:42:06

回答

87

您可以使用「group by」+「orderby」。有關詳細信息,

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

針對this postLINQ 101(現已刪除):

如果你有一些自定義對象的列表,那麼你需要通過特定的屬性使用custom comparer或組。

還查詢無法顯示結果。向我們顯示完整的代碼以獲得更好的幫助。基於

您最新的更新:

您有這行代碼:

group xx by xx into g 

由於xx是一個自定義對象系統不知道如何給一個項目對相互比較。 正如我已經寫過的,你需要指導編譯器,並提供一些將用於對象比較或提供自定義比較器的屬性。這裏有一個例子:

請注意,我用Foo.Name作爲重點 - 即對象將基於的名稱屬性值進行分組。

有一個問題 - 你根據它們的名字將兩個對象視爲重複對象,但是Id呢?在我的例子中,我只是將組中的第一個對象作爲Id。如果你的對象有不同的ID,那可能是一個問題。

//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

只是顯示結果到自定義中繼器。 – 2009-01-18 04:38:09

+0

斯科特,只顯示你的代碼 – aku 2009-01-18 04:39:43

36

略短版使用方法鏈:

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); 
} 
4

其他解決方案使用GroupByGroupBy慢(它在內存中保存的所有元素),所以我寫了我自己的方法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

下面是完整的程序,請檢查該

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

你也可以做解釋:

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