Discuss GroupBy Operator in LINQ

The GroupBy operator takes a sequence of items, organize that sequence into a group based on a specific key and return a sequence of IGrouping<K,V>, where K is the key and V is the value. This is the only operator that belongs to the Grouping Operators category.

The following is the console application that we will work on.

Create a class “Student” with three auto-implemented properties.

  1. class Student {  
  2.     public string Name {  
  3.         get;  
  4.         set;  
  5.     }  
  6.     public string Gender {  
  7.         get;  
  8.         set;  
  9.     }  
  10.     public string StudentType {  
  11.         get;  
  12.         set;  
  13.     }  
  14. }  
  15. In the Main method create a list of student.  
  16. class Program {  
  17.     static void Main(string[] args) {  
  18.         List < Student > StudenrList = new List < Student > () {  
  19.             new Student() {  
  20.                 Name = "Michael", Gender = "Male", StudentType = "Diploma"  
  21.             },  
  22.             new Student() {  
  23.                 Name = "Trevor", Gender = "Male", StudentType = "Graduate"  
  24.             },  
  25.             new Student() {  
  26.                 Name = "Aiden", Gender = "Male", StudentType = "Diploma"  
  27.             },  
  28.             new Student() {  
  29.                 Name = "Sam", Gender = "Male", StudentType = "Graduate"  
  30.             },  
  31.             new Student() {  
  32.                 Name = "Max", Gender = "Male", StudentType = "Diploma"  
  33.             },  
  34.             new Student() {  
  35.                 Name = "Sara", Gender = "Female", StudentType = "Graduate"  
  36.             },  
  37.             new Student() {  
  38.                 Name = "Lara", Gender = "Female", StudentType = "Diploma"  
  39.             },  
  40.             new Student() {  
  41.                 Name = "Natasha", Gender = "Female", StudentType = "Graduate"  
  42.             },  
  43.             new Student() {  
  44.                 Name = "Bob", Gender = "Male", StudentType = "Diploma"  
  45.             },  
  46.             new Student() {  
  47.                 Name = "Kevin", Gender = "Male", StudentType = "Graduate"  
  48.             }  
  49.         };  
  50.     }  
  51. }  

Example 1

Now, let's say we want to get the total number of students by StudentType and for that we can group all the students by StudentType.

var student = from students in StudentList
group students by students.StudentType;

The preceding example shows that we are using a SQL-like query to group the students by StudentType.

Now, all we need to do is add the following foreach block that will provide us the key, in other words StudentType and the total number of students belong to a specific StudentType.

  1. foreach(var stud in student) {  
  2. Console.WriteLine(stud.Key + " = " + stud.Count());  

Run the application



We can do the same thing using the GroupBy extension method present in the System.Linq namespace.

  1. //GroupBy extension method  
  2. var stud = StudentList.GroupBy(x = > x.StudentType);  
  3. foreach(var s in stud)   
  4. {  
  5.     Console.WriteLine(s.Key + " ---- " + s.Count());  
  6. }  
Example 2

Let's say that for some reason with the total number of students, we also want the names of the students. For this, we will use a nested foreach loop.

From the first foreach loop, we will get the total number of students present in the respective group using the key. Next, let's retrieve the records in the nested foreach loop.
  1. foreach(var s in student)   
  2. {  
  3.     Console.WriteLine(s.Key + " ---- " + s.Count());  
  4.     foreach(var ss in s)   
  5.     {  
  6.         Console.WriteLine(ss.Name);  
  7.     }  

Run the application.



Example 3

Let's say we want to sort the StudentType in descending order and then Name by ascending order and for that we can use OrderByDescending and ThenBy LINQ extension methods.

  1. #region Example 3  
  2. //extension method and Sql like query  
  3. var stud = from students in StudentList.OrderByDescending(x = > x.StudentType).ThenBy(y = > y.Name)  
  4. group students by students.StudentType;  
  5. foreach(var item in stud)   
  6. {  
  7.     Console.WriteLine("----------" + item.Key + "----------");  
  8.     foreach(var x in item)  
  9.     {  
  10.         Console.WriteLine(x.Name);  
  11.     }  
  12. }#endregion

Run the application.

In example two, we got the unsorted output.



After sorting, here is the final result.



The output in the preceding example shows that the preceding key is sorted in descending order and the Student name is sorted in ascending order.

In the next example, we will see how to group the sequence of items based on multiple keys.

Example 4

  1. #region GroupBy multiple keys  
  2. var studentByMultipleKey = StudentList.GroupBy(x = > new {  
  3.     x.StudentType, x.Gender  
  4. })  
  5.     .OrderBy(x = > x.Key.StudentType)  
  6.     .ThenBy(x = > x.Key.Gender)  
  7.     .Select(x = > new {  
  8.     StudentType = x.Key.StudentType,  
  9.     Gender = x.Key.Gender,  
  10.     Stud = x.OrderBy(y = > y.Name)  
  11. });  
  12. foreach(var item in studentByMultipleKey) {  
  13.     Console.WriteLine("{0} Students with Gender {1} ", item.StudentType, item.Gender);  
  14.     foreach(var i in item.Stud) {  
  15.         Console.WriteLine(i.Name);  
  16.     }  
  17.     Console.WriteLine();  
  18. }#endregion  
Run the application.



Explanation

To group a sequence based on multiple keys we need to pass a new anonymous lambda expression in the GroupyBy extension method.
  1. StudentList.GroupBy(x => new { x.StudentType, x.Gender })  

Here, we are stating the first group of students by StudentType and then by Gender.

Next, we used the OrderBy operator to sort the StudentType in ascending order and then by gender.

  1. OrderBy(x => x.Key.StudentType)  
  2. ThenBy(x => x.Key.Gender)  
The Select operator can be used to project a new anonymous type and that is what we are doing here.
  1. Select(x = > new   
  2. {  
  3.     StudentType = x.Key.StudentType,  
  4.     Gender = x.Key.Gender,  
  5.     Stud = x.OrderBy(y = > y.Name)  
  6. });

Here we passed the first key, x.key.StudentType, into a new anonymous type StudentType. Then we passed the second key in the same manner and in the end we passed the third anonymous type that expects a new anonymous type of IOrderedEnumerable of Student that will provide us the collection of students present in the StudentList.



Summary

In this article, we learned the various forms in which we can group and sort the records. We have also seen how to group elements based on multiple keys.

I hope you liked it. Thank you.