Cách nhận bản ghi đầu tiên trong mỗi nhóm bằng Linq


133

Xem xét các hồ sơ sau đây:

   Id          F1            F2             F3 
 -------------------------------------------------
   1           Nima          1990           10
   2           Nima          1990           11
   3           Nima          2000           12
   4           John          2001           1
   5           John          2002           2 
   6           Sara          2010           4

Tôi muốn nhóm theo dựa trên F1trường và sắp xếp theo Idvà nhận tất cả các trường từ bản ghi đầu tiên của nhóm tương tự với các bản ghi này:

   Id          F1            F2             F3 
 -------------------------------------------------
   1           Nima          1990           10
   4           John          2001           1
   6           Sara          2010           4

Làm thế nào tôi có thể làm điều này bằng cách sử dụng linq?

Câu trả lời:


127
    var res = from element in list
              group element by element.F1
                  into groups
                  select groups.OrderBy(p => p.F2).First();

4
Rất vui vì tôi đã tìm thấy điều này. Tôi đã nhận được thông báo lỗi "Phương thức 'Đầu tiên' chỉ có thể được sử dụng làm thao tác truy vấn cuối cùng. Thay vào đó, hãy xem xét sử dụng phương thức 'FirstOrDefault' trong trường hợp này." từ ví dụ của bạn. Chỉ hoạt động trong danh sách tôi đã làm sau khi truy vấn được truyền myResult.ToList () cho một phương thức. Tuy nhiên, việc sử dụng FirstOrDefault đã giải quyết được nó
kể từ

Có phải OrderBy(p => p.Id), họ muốn nó được đặt hàng bởi ID không phải là cột năm.
Mike Flynn

Bạn có thể vui lòng cung cấp một số trợ giúp cho việc này không: stackoverflow.com/questions/44764687/iêng
Si8

Điều gì nếu muốn lấy mục đầu tiên và cuối cùng từ nhóm?
Sandeep Pandey

176
var result = input.GroupBy(x=>x.F1,(key,g)=>g.OrderBy(e=>e.F2).First());

2
Điều này chỉ cho tôi cách sử dụng cú pháp Fluent. Quá tải cho GroupBy dường như cung cấp cho bạn rất nhiều sức mạnh - một để thêm vào danh sách dài học tập!
rogersillito

1
@rogersillito đó là lý do tại sao nó được gọi là truy vấn (Truy vấn tích hợp ngôn ngữ - LINQ), GroupBy cũng có nhiều tình trạng quá tải nhưng chỉ có một số ít được sử dụng, còn tùy thuộc vào sở thích cá nhân, như một số người thích viết nó như .GroupBy(x=>x.F1).Select(g=>...), nó có thể trông dễ hiểu hơn
Vua King

11
Bạn nên thay thế .First()bằng .FirstOrDefault()hoặc bạn sẽ có được ngoại lệ:The method 'First' can only be used as a final query operation. Consider using the method 'FirstOrDefault' in this instance instead.
Nikolay Kostov

5
@NikolayKostov Tôi biết về điều đó, nhưng tôi giả sử LINQ ở đây được sử dụng như LINQ-to-object, không phải LINQ-to-entity, vì vậy chúng tôi có thể sử dụng một cách an toàn .First(). Câu hỏi của OP trông thực sự giống như chỉ quan tâm đến linq-to-object, mặc dù anh ta cũng gắn thẻ câu hỏi với linq-to-entities(không chắc anh ta có hiểu đó là gì không).
Vua King

1
Tôi thích câu trả lời này, Nice one.
Ajas Aju

8

Awnser của @Alireza là hoàn toàn chính xác, nhưng bạn phải lưu ý rằng khi sử dụng mã này

var res = from element in list
          group element by element.F1
              into groups
              select groups.OrderBy(p => p.F2).First();

đó là simillar với mã này bởi vì bạn sắp xếp danh sách và sau đó thực hiện nhóm để bạn có được hàng đầu tiên của nhóm

var res = (from element in list)
          .OrderBy(x => x.F2)
          .GroupBy(x => x.F1)
          .Select()

Bây giờ nếu bạn muốn làm một cái gì đó phức tạp hơn như lấy cùng một kết quả nhóm nhưng lấy phần tử đầu tiên của F2 và phần tử cuối cùng của F3 hoặc một cái gì đó tùy chỉnh hơn, bạn có thể làm điều đó bằng cách nghiên cứu mã dưới đây

 var res = (from element in list)
          .GroupBy(x => x.F1)
          .Select(y => new
           {
             F1 = y.FirstOrDefault().F1;
             F2 = y.First().F2;
             F3 = y.Last().F3;
           });

Vì vậy, bạn sẽ nhận được một cái gì đó như

   F1            F2             F3 
 -----------------------------------
   Nima          1990           12
   John          2001           2
   Sara          2010           4

Dấu phân cách hoặc dấu phân cách của đối tượng mới phải là dấu phẩy chứ không phải dấu hai chấm. Vui lòng kiểm tra.
Naredla Nithesh Reddy

3

Sử dụng nó để đạt được những gì bạn muốn. Sau đó quyết định những thuộc tính bạn muốn trả lại.

yourList.OrderBy(l => l.Id).GroupBy(l => new { GroupName = l.F1}).Select(r => r.Key.GroupName)
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.