Toán tử nhóm trong LINQ

Các toán tử nhóm làm điều tương tự như mệnh đề Group By của truy vấn SQL. Các toán tử nhóm tạo một nhóm các phần tử dựa trên khóa đã cho.

Nhóm này được lưu trữ trong một kiểu danh sách đặc biệt được triển khai interface IGrouping<TKey, TSource>. Trong đó, TKey là một giá trị khóa và TSource là tập hợp các phần tử khớp với giá trị khóa.

Bảng sau liệt kê tất cả toán tử nhóm có sẵn trong LINQ.

Toán tử Mô tả
GroupBy Toán tử GroupBy trả về các nhóm phần tử dựa trên một số giá trị khóa. Mỗi nhóm được đại diện bởi đối tượng IGrouping<TKey, TEuity>.
ToLookup ToLookup giống như GroupBy; sự khác biệt duy nhất là việc thực thi GroupBy bị hoãn trong khi thực thi ToLookup là ngay lập tức.

Toán tử nhóm là một trong những toán tử truy vấn chuẩn của LINQ.

Toán tử truy vấn chuẩn của LINQ | Comdy
Các toán tử truy vấn chuẩn trong LINQ là các phương thức mở rộng cho các kiểu IEnumerable<T> và IQueryable<T>.

Toán tử nhóm GroupBy trong LINQ

Toán tử GroupBy trả về một nhóm các phần tử từ danh sách đã cho dựa trên một số giá trị khóa. Mỗi nhóm được đại diện bởi đối tượng IGrouping<TKey, TEuity>.

Ngoài ra, phương thức mở rộng GroupBy có tám phương thức quá tải, vì vậy bạn có thể sử dụng phương thức phù hợp dựa trên yêu cầu của bạn trong cú pháp phương thức LINQ.

Tip: Cú pháp truy vấn LINQ có thể kết thúc bằng mệnh đề groupby hoặc select.

Kết quả của các toán tử GroupBy là một tập hợp các nhóm. Ví dụ: GroupBy trả về IEnumerable<IGrouping<TKey,Student>> từ danh sách Student:

Toán tử nhóm GroupBy trong LINQ

Mệnh đề GroupBy trong Cú pháp truy vấn LINQ

Ví dụ sau đây tạo ra một nhóm sinh viên có cùng độ tuổi. Những sinh viên cùng tuổi sẽ được gom vào cùng một nhóm. Mỗi nhóm sẽ có khóa là tuổi và một danh sách sinh viên có tuổi bằng với tuổi của khóa.

// Student collection
IList<Student> studentList = new List<Student>() 
{ 
    new Student() { StudentID = 1, StudentName = "John", Age = 18 },
    new Student() { StudentID = 2, StudentName = "Steve",  Age = 21 },
    new Student() { StudentID = 3, StudentName = "Bill",  Age = 18 },
    new Student() { StudentID = 4, StudentName = "Ram" , Age = 20 },
    new Student() { StudentID = 5, StudentName = "Ron" , Age = 21 } 
};

var groupedResult = from s in studentList
                    group s by s.Age;

//iterate each group        
foreach (var ageGroup in groupedResult)
{
    //Each group has a key
    Console.WriteLine("Age Group: {0}", ageGroup.Key);  
             
    // Each group has inner collection
    foreach(Student s in ageGroup)
    {
        Console.WriteLine("Student Name: {0}", s.StudentName);
    }
}

Đây là kết quả khi biên dịch và thực thi chương trình:

Age Group: 18
Student Name: John
Student Name: Bill
Age Group: 21
Student Name: Steve
Student Name: Ron
Age Group: 20
Student Name: Ram

Như bạn có thể thấy trong ví dụ trên, bạn có thể duyệt các nhóm bằng cách sử dụng vòng lặp foreach, trong đó mỗi nhóm chứa một khóa và một danh sách bên trong. Hình dưới đây cho thấy kết quả trong chế độ Debug.

Toán tử nhóm GroupBy trong LINQ

Phương thức GroupBy trong Cú pháp phương thức LINQ

Phương thức mở rộng GroupBy() hoạt động theo cách tương tự trong cú pháp phương thức. Cần chỉ định biểu thức lambda cho tên trường được chọn làm khóa trong phương thức mở rộng GroupBy.

// Student collection
IList<Student> studentList = new List<Student>() 
{ 
    new Student() { StudentID = 1, StudentName = "John", Age = 18 },
    new Student() { StudentID = 2, StudentName = "Steve",  Age = 21 },
    new Student() { StudentID = 3, StudentName = "Bill",  Age = 18 },
    new Student() { StudentID = 4, StudentName = "Ram" , Age = 20 },
    new Student() { StudentID = 5, StudentName = "Ron" , Age = 21 } 
};

var groupedResult = studentList.GroupBy(s => s.Age);

//iterate each group        
foreach (var ageGroup in groupedResult)
{
    //Each group has a key
    Console.WriteLine("Age Group: {0}", ageGroup.Key);  
             
    // Each group has inner collection
    foreach(Student s in ageGroup)
    {
        Console.WriteLine("Student Name: {0}", s.StudentName);
    }
}

Đây là kết quả khi biên dịch và thực thi chương trình:

Age Group: 18
Student Name: John
Student Name: Bill
Age Group: 21
Student Name: Steve
Student Name: Ron
Age Group: 20
Student Name: Ram

Toán tử nhóm ToLookup trong LINQ

ToLookup cũng giống như GroupBy; sự khác biệt duy nhất là việc thực thi GroupBy bị hoãn lại, trong khi thực thi ToLookup là ngay lập tức.

Ngoài ra, ToLookup chỉ được áp dụng theo cú pháp phương thức LINQ. ToLookup không được hỗ trợ trong cú pháp truy vấn LINQ.

Dưới đây là ví dụ minh họa sử dụng ToLookup trong LINQ:

// Student collection
IList<Student> studentList = new List<Student>() 
{ 
    new Student() { StudentID = 1, StudentName = "John", Age = 18 },
    new Student() { StudentID = 2, StudentName = "Steve",  Age = 21 },
    new Student() { StudentID = 3, StudentName = "Bill",  Age = 18 },
    new Student() { StudentID = 4, StudentName = "Ram" , Age = 20 },
    new Student() { StudentID = 5, StudentName = "Ron" , Age = 21 } 
};

var groupedResult = studentList.ToLookup(s => s.Age);

//iterate each group        
foreach (var ageGroup in groupedResult)
{
    //Each group has a key
    Console.WriteLine("Age Group: {0}", ageGroup.Key);  
             
    // Each group has inner collection
    foreach(Student s in ageGroup)
    {
        Console.WriteLine("Student Name: {0}", s.StudentName);
    }
}

Đây là kết quả khi biên dịch và thực thi chương trình:

Age Group: 18
Student Name: John
Student Name: Bill
Age Group: 21
Student Name: Steve
Student Name: Ron
Age Group: 20
Student Name: Ram

Những điểm cần nhớ về toán tử nhóm trong LINQ

  1. GroupBy và ToLookup trả về một danh sách có khóa và danh sách bên trong dựa trên giá trị trường khóa.
  2. Việc thực thi GroupBy được hoãn lại trong khi đó ToLookup là ngay lập tức.
  3. Cú pháp truy vấn LINQ có thể kết thúc bằng mệnh đề groupby hoặc select.


Bài viết liên quan:

Bạn sẽ tìm hiểu một số truy vấn LINQ phức tạp trong hướng dẫn này.

Từ khóa let, into trong LINQ có tác dụng gì? Hướng dẫn khai báo và sử dụng từ khóa let, into trong LINQ.

Trì hoãn thực thi truy vấn LINQ là gì? Thực thi ngay lập tức truy vấn LINQ là gì? Làm sao để thực thi truy vấn LINQ.