2009-01-18 37 views
63

Tôi có một danh sách các mụcLàm thế nào để đếm Lặp lại trong Danh sách với LINQ

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

Tôi muốn đưa chúng trở lại danh sách như vậy cũng có nghĩa là tôi muốn sắp xếp theo số lượng bản sao cao nhất.

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

Hãy cho tôi biết làm thế nào tôi có thể làm điều này với LINQ và C#.

Cảm ơn tất cả

EDIT 2 kết 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(); 

truy vấn này sẽ hiển thị các kết quả này:

  • 1 chào lần thế giới
  • 1 chào lần thế giới
  • 1 Xin chào thế giới.
  • 1 chào lần thế giới
  • 1 chào lần thế giới
  • 1 chào lần thế giới
  • 1 Hello World.
  • 1 chào lần thế giới

Nó mang lại cho tôi số lượng và tên, nhưng nó không cho tôi ID của trò chơi ....

Nó sẽ hiển thị:

  • 6 xin chào thế giới lần 234234
  • 2 Xin chào thế giới. 23432432
+0

cho kết quả rõ ràng là chương trình xử lý tất cả các mục của bạn là khác biệt - như tôi đã nói, bạn cần triển khai tùy chỉnh so sánh, nếu không thì không thể chọn các giá trị riêng biệt – aku

Trả lời

87

Bạn có thể sử dụng "nhóm theo" + "orderby". Xem LINQ 101 để biết chi tiết

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

Để đối phó với this post (nay đã bị xóa):

Nếu bạn có một danh sách của một số đối tượng tùy chỉnh thì bạn cần phải sử dụng custom comparer hoặc nhóm bằng tài sản cụ thể.

Truy vấn cũng không thể hiển thị kết quả. Hiển thị cho chúng tôi mã hoàn chỉnh để nhận trợ giúp tốt hơn.

Dựa trên bản cập nhật mới nhất của bạn:

Bạn có dòng mã này:

group xx by xx into g 

Từ xx là một hệ thống đối tượng tùy chỉnh không biết làm thế nào để so sánh một mặt hàng chống lại khác. Như tôi đã viết, bạn cần hướng dẫn trình biên dịch và cung cấp một số thuộc tính sẽ được sử dụng trong đối tượng so sánh hoặc cung cấp so sánh tùy chỉnh. Dưới đây là một ví dụ:

Lưu ý rằng tôi sử dụng Foo.Name như một chìa khóa - ví dụ: đối tượng sẽ được nhóm lại dựa trên giá trị của Tên tài sản.

Có một sự bắt giữ - bạn đối xử với 2 đối tượng trùng lặp dựa trên tên của chúng, nhưng Id thì sao? Trong ví dụ của tôi, tôi chỉ lấy Id của đối tượng đầu tiên trong một nhóm. Nếu các đối tượng của bạn có các Id khác nhau, nó có thể là một vấn đề.

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

chỉ hiển thị kết quả cho bộ lặp tùy chỉnh .... –

+0

Scott, chỉ hiển thị mã của bạn – aku

+0

Xong, Bây giờ bạn có thể xem nhanh những gì đang xem. –

36

Hơi ngắn hơn phiên bản sử dụng phương pháp chuỗi:

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

đơn giản để hiểu và làm việc tuyệt vời –

+1

Chắc chắn là giải pháp tốt nhất - cảm ơn! –

+0

Tính đơn giản với chuyên môn. – Hitsa00

4

Các giải pháp khác sử dụng GroupBy. GroupBy là chậm (nó chứa tất cả các yếu tố trong bộ nhớ) vì vậy tôi đã viết phương pháp riêng của tôi 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

Dưới đây là chương trình hoàn chỉnh xin vui lòng kiểm tra này

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

Bạn cũng có thể làm từ điển:

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); 
     } 
Các vấn đề liên quan