2013-04-07 71 views
7

Tôi có một bộ sưu tập, ví dụ:Sử dụng groupby và Max trong LINQ Lambda Expressions

**id1, id2, value** 
    1 9 12 
    2 9  6 
    3 11 8 
    4 11 87 

Tôi muốn sử dụng LINQ và nhận được kết quả sau:

**value** 
    6 
    87 

T.B.

id1 - select MAX; 
id2 - group column; 

Tôi cần một câu trả lời theo hình thức

var result = list.GroupBy(x=>x.id2).select(s=>s.value); 

Tôi hy vọng sự giúp đỡ của bạn.

+0

Bạn chưa bày tỏ câu hỏi của bạn rõ ràng ở tất cả . * Tại sao * bạn mong đợi kết quả là 6 và 87? Tại sao bạn nhóm theo id1 khi mỗi hàng có id1 khác nhau? Nếu bạn được nhóm theo id2 mà sẽ có ý nghĩa hơn, nhưng sau đó kết quả nên là 12 và 87, không phải 6 và 87. Hãy dành chút thời gian để làm cho câu hỏi của bạn rõ ràng. –

+0

Nhưng '6 <12' và' 87> 8'; vui lòng giải thích. –

+0

Tôi nghĩ anh ấy muốn nhóm theo id2 và chọn Giá trị tối đa từ mỗi nhóm –

Trả lời

23

EDIT: Được rồi, bây giờ chúng tôi đã có một bộ hơi rõ ràng hơn về các yêu cầu (mặc dù vẫn còn xa mới bằng văn bản rõ ràng) cách tiếp cận đơn giản nhất có lẽ sẽ là:

var maxes = list.GroupBy(x => x.id2, 
         (key, xs) => xs.OrderByDescending(x => x.id1) 
             .First() 
             .value); 

Thật không may LINQ không cung cấp một cách đơn giản nhận được "phần tử có giá trị tối đa" (thay vì chính giá trị tối đa). Tôi có một phương pháp trong MoreLINQ mà thực hiện điều này, mặc dù gọi là MaxBy:

var maxes = list.GroupBy(x => x.id2, 
         (key, xs) => xs.MaxBy(x => x.id2).value); 

Original câu trả lời (Grouping bởi id2, lấy giá trị lớn nhất)

tôi trả lời giả bạn thực sự có nghĩa là nhóm theo id2 thay vì id1 và bạn thực sự muốn kết quả của 12 và 87 thay vì 6 và 87. Trong trường hợp đó, bạn muốn:

var maxes = list.GroupBy(x => x.id2, (id, xs) => xs.Max(x => x.value)); 

Hoặc (có thể đơn giản hơn để hiểu):

var maxes = list.GroupBy(x => x.id2) 
       .Select(xs => xs.Max(x => x.value)); 

Hoặc:

var maxes = list.GroupBy(x => x.id2, x => x.value) 
       .Select(values => values.Max()); 

Hoặc:

var maxes = list.GroupBy(x => x.id2,  // Key selector 
         x => x.value, // Element selector 
         (key, values) => values.Max()); // Result selector 

Hoặc thậm chí:

var maxes = list.GroupBy(x => x.id2) 
       .Select(xs => xs.Select(x => x.value).Max()); 

Như bạn thấy, GroupBy có nhiều quá tải :)

Hoặc bạn có thể sử dụng một biểu thức truy vấn:

var maxes = from x in list 
      group x.value by x.id2 into values 
      select values.Max(); 

Bạn không nên giới hạn mình vào một trong hai biểu thức truy vấn hoặc các phương pháp khuyến nông phiên bản - điều quan trọng là phải hiểu cả hai, vì vậy bạn có thể sử dụng bất cứ điều gì thích hợp nhất.

+0

id1 - chọn MAX; id2 - cột nhóm; – Pavel

+0

cảm ơn câu trả lời của bạn, nhưng tôi phải chọn VALUE cho mỗi id2 trong đó id1 - MAX – Pavel

+0

@PavelIvanov: Ok, tôi nghĩ * Tôi hiểu ý bạn là gì, nhưng bạn thực sự cần nỗ lực hơn để làm rõ điều này trong tương lai. Xem chỉnh sửa của tôi cho một câu trả lời hy vọng sẽ giải quyết được điều này ... –

4

Rõ ràng OP muốn các Value với tối đa Id1 trong Id2:

dữ liệu mẫu:

public class Row 
{ 
    public int Id1; 
    public int Id2; 
    public int Value; 
} 

List<Row> rows = new List<Row>(){ 
    new Row(){Id1=1,Id2=9,Value=12}, 
    new Row(){Id1=2,Id2=9,Value=6}, 
    new Row(){Id1=3,Id2=11,Value=8}, 
    new Row(){Id1=4,Id2=11,Value=87} 
}; 

Giải pháp:

List<int> res = rows.GroupBy(r => r.Id2) 
        .Select(g => g.OrderByDescending(i=>i.Id1).First().Value) 
        .ToList(); 
0

Trong trường hợp nó giúp những người khác, tôi đã có một tình huống tương tự, ngoại trừ nhiều bản ghi cần phải được trả lại thay vì một bản ghi duy nhất.

Ví dụ:

**id1, id2, value** 
    1 9 12 
    2 9  6 <- 
    2 9  7 <- 
    3 11 8 
    4 11 87 <- 
    4 11 88 <- 

Lợi nhuận sau bốn hồ sơ trên như hai danh sách của hai kỷ lục (đếm được của enumerables):

var maxes = from x in list 
      group x by x.id2 into xs 
      select new {values = xs.Where(x => x.id1 == xs.Max(y => y.id1))}; 

hoặc

var maxes = list.GroupBy(x => x.id2, 
      (key, xs) => new 
      { 
       values = xs.Where(x => x.id1 == xs.Max(y => y.id1)) 
      }); 
Các vấn đề liên quan