LINQ với nhóm và đếm


221

Điều này khá đơn giản nhưng tôi thua lỗ: Đưa ra loại dữ liệu này:

UserInfo(name, metric, day, other_metric)

và tập dữ liệu mẫu này:

joe  1 01/01/2011 5
jane 0 01/02/2011 9
john 2 01/03/2011 0
jim  3 01/04/2011 1
jean 1 01/05/2011 3
jill 2 01/06/2011 5
jeb  0 01/07/2011 3
jenn 0 01/08/2011 7

Tôi muốn truy xuất một bảng liệt kê các số liệu theo thứ tự (0,1,2,3 ..) với tổng số lần xảy ra. Vì vậy, từ bộ này, bạn kết thúc với:

0 3    
1 2    
2 2    
3 1

Tôi đang vật lộn với cú pháp LINQ nhưng bị mắc kẹt ở đâu để đặt một nhóm và đếm .... bất kỳ trợ giúp ??

POST Chỉnh sửa: Tôi không bao giờ có thể làm cho các câu trả lời được đăng hoạt động vì chúng luôn trả về một bản ghi với số lượng khác nhau. Tuy nhiên, tôi đã có thể kết hợp một ví dụ LINQ với SQL đã hoạt động:

        var pl = from r in info
                 orderby r.metric    
                 group r by r.metric into grp
                 select new { key = grp.Key, cnt = grp.Count()};

Kết quả này đã cho tôi một bộ hồ sơ được đặt hàng với 'số liệu' và số lượng người dùng được liên kết với từng hồ sơ. Tôi rõ ràng là người mới đối với LINQ nói chung và với con mắt chưa được huấn luyện của tôi, cách tiếp cận này có vẻ rất giống với cách tiếp cận LINQ thuần túy nhưng đã cho tôi một câu trả lời khác.


Có tôi có, nhưng lời giải thích của jimmy đã giúp tôi nhiều hơn như vậy. Tuy nhiên tôi không bao giờ có thể làm cho tấm gương của anh ấy hoạt động nhưng nó đã đưa tôi đến một hướng mới.
Gio

@Jimmy đã sử dụng cú pháp chức năng cho các biểu thức LINQ thay vì cú pháp truy vấn LINQ tiêu chuẩn, cộng với việc anh quyết định hiển thị việc thực thi ngay lập tức các chức năng đó thay vì định dạng thực thi bị trì hoãn. Đối với một người mới sẽ khó hiểu. Không biết tại sao anh ta làm điều đó.
Richard Robertson

Câu trả lời:


394

Sau khi gọi GroupBy, bạn nhận được một loạt các nhóm IEnumerable<Grouping>, trong đó mỗi Nhóm tự thể hiện việc Keysử dụng để tạo nhóm và cũng là một IEnumerable<T>trong bất kỳ mục nào trong tập dữ liệu gốc của bạn. Bạn chỉ cần gọi Count()vào Nhóm đó để có được tổng số phụ.

foreach(var line in data.GroupBy(info => info.metric)
                        .Select(group => new { 
                             Metric = group.Key, 
                             Count = group.Count() 
                        })
                        .OrderBy(x => x.Metric)
{
     Console.WriteLine("{0} {1}", line.Metric, line.Count);
}


Đây là một câu trả lời cực kỳ nhanh chóng nhưng tôi gặp một chút vấn đề với dòng đầu tiên, cụ thể là "data.groupby (thông tin => thông tin.metric)"

Tôi giả sử bạn đã có một danh sách / mảng của một số classtrông giống như

class UserInfo {
    string name;
    int metric;
    ..etc..
} 
...
List<UserInfo> data = ..... ;

Khi bạn làm như vậy data.GroupBy(x => x.metric), điều đó có nghĩa là "cho mỗi phần tử xtrong IEnumerable được xác định bởi data, tính toán nó .metric, sau đó nhóm tất cả các phần tử có cùng số liệu thành một Groupingvà trả về một IEnumerabletrong tất cả các nhóm kết quả.

    <DATA>           | Grouping Key (x=>x.metric) |
joe  1 01/01/2011 5  | 1
jane 0 01/02/2011 9  | 0
john 2 01/03/2011 0  | 2
jim  3 01/04/2011 1  | 3
jean 1 01/05/2011 3  | 1
jill 2 01/06/2011 5  | 2
jeb  0 01/07/2011 3  | 0
jenn 0 01/08/2011 7  | 0

nó sẽ dẫn đến kết quả sau khi nhóm:

(Group 1): [joe  1 01/01/2011 5, jean 1 01/05/2011 3]
(Group 0): [jane 0 01/02/2011 9, jeb  0 01/07/2011 3, jenn 0 01/08/2011 7]
(Group 2): [john 2 01/03/2011 0, jill 2 01/06/2011 5]
(Group 3): [jim  3 01/04/2011 1]

Đây là một câu trả lời cực kỳ nhanh chóng nhưng tôi có một chút vấn đề với dòng đầu tiên, cụ thể là "data.groupby (thông tin => thông tin.metric)". Rõ ràng 'dữ liệu' là tập dữ liệu hiện tại nhưng represet 'info.metric' là gì? định nghĩa lớp?
Gio

"Info.metric" sẽ là thuộc tính / trường số liệu trên lớp UserInfo mà bạn đã đề cập trong câu hỏi của mình.
lee-m

1
Cảm ơn đã tìm ra điều đó nhưng thực ra điều này dường như mang lại cho tôi một giá trị duy nhất - cụ thể là tổng số lượng số liệu khác nhau. Trong ví dụ này, tôi nhận được "số liệu 4" cho biết tôi có bao nhiêu số đếm khác nhau.
Gio

1
Ồ Bạn hoàn toàn giải thích nhóm !! Điều đó một mình là giá trị bài .... tôi vẫn nhận được kết quả "số liệu 4" nhưng cảm ơn!
Gio

4
Bắt đầu câu trả lời này, "sau khi gọi GroupBy, bạn nhận được một loạt các nhóm IEnumerable <Grouping>, trong đó mỗi Nhóm tự hiển thị Khóa được sử dụng để tạo nhóm và cũng là một <T> bất kỳ mục nào trong dữ liệu gốc của bạn. thiết lập ", là lời giải thích rõ ràng nhất về LINQ GroupBy tôi đã đọc, cảm ơn bạn.
dumbledad

48

Giả sử userInfoListList<UserInfo>:

        var groups = userInfoList
            .GroupBy(n => n.metric)
            .Select(n => new
            {
                MetricName = n.Key,
                MetricCount = n.Count()
            }
            )
            .OrderBy(n => n.MetricName);

Hàm lambda cho GroupBy(), n => n.metriccó nghĩa là nó sẽ lấy trường metrictừ mọi UserInfođối tượng gặp phải. Loại ntùy thuộc vào ngữ cảnh, trong lần xuất hiện đầu tiên, đó là loại UserInfo, vì danh sách chứa UserInfocác đối tượng. Trong lần xuất hiện thứ hai nlà kiểu Grouping, vì bây giờ nó là một danh sách các Groupingđối tượng.

Groupings có các phương thức mở rộng như .Count(), .Key()và hầu hết mọi thứ bạn mong đợi. Giống như bạn sẽ kiểm tra .Lenghttrên một string, bạn có thể kiểm tra .Count()một nhóm.


23
userInfos.GroupBy(userInfo => userInfo.metric)
        .OrderBy(group => group.Key)
        .Select(group => Tuple.Create(group.Key, group.Count()));

1
lỗi đánh máy nhỏ -> group.keytrong phần Chọn (...) phải làgroup.Key
Jan
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.