Introduction

LINQ is a great technology provided by Microsoft to manage data in .Net languages. Grouping is a very powerful feature provided by LINQ that transforms a collection in groups where each group has a key associated with it.

Note: GroupBy performs a deferred execution which means the query is only executed when the records are processed using a foreach loop.

To understand the concept completely, I have created some examples and divided them into the following sections.

Group By: Single key

Group By: Multiple keys
Sample Class

I have create one sample class student that I will use to demonstrate the examples.
  1. class student
  2. {
  3. public int id;
  4. public string name;
  5. public int standard;
  6. public int age;
  7. public static List<student> getstudents()
  8. {
  9. List<student> Students = new List<student>()
  10. {
  11. new student{id = 1, name ="ram", age = 20, standard =12},
  12. new student{id = 2, name ="zip", age = 18, standard =10},
  13. new student{id = 3, name ="any", age = 19, standard =12},
  14. new student{id = 4, name ="Ian", age = 18, standard =10},
  15. new student{id = 5, name ="john", age = 17, standard =10},
  16. new student{id = 6, name ="bob", age = 19, standard =12},
  17. new student{id = 7, name ="moni", age = 18, standard =10},
  18. new student{id = 8, name ="sri", age = 19, standard =12},
  19. new student{id = 9, name ="dummy" , age = 17, standard =10},
  20. new student{id = 10, name ="hon" , age = 17, standard =10},
  21. };
  22. return Students;
  23. }
  24. }
Examples

Group By: Single key

This example will group students by standard (class) and display all the grouped records.

  1. List<student> studentlist = student.getstudents();
  2. var result = from stu in studentlist
  3. group stu by stu.standard
  4. into egroup
  5. orderby egroup.Key
  6. select egroup;
  7. foreach (var group in result)
  8. {
  9. Console.WriteLine("class - {0} ", group.Key);
  10. Console.WriteLine("{0} -- {1} -- {2} -- {3}", "ID", "NAME", "AGE", "CLASS");
  11. foreach (var _student in group)
  12. {
  13. Console.WriteLine("{0} -- {1} -- {2} -- {3}", _student.id, _student.name, _student.age, _student.standard);
  14. }
  15. Console.WriteLine("---------------------------------------------");
  16. }
  17. Console.ReadKey();
Output

cmd output

This example works similar to example 1 but uses a lambda expression to do the job.

  1. List<student> studentlist = student.getstudents();
  2. //result using lamba
  3. var resultlamba = studentlist.GroupBy(stu => stu.standard).OrderBy(stu => stu.Key);
  4. foreach (var group in resultlamba)
  5. {
  6. Console.WriteLine("class - {0} ", group.Key);
  7. Console.WriteLine("{0} -- {1} -- {2} -- {3}", "ID", "NAME", "AGE", "CLASS");
  8. foreach (var _student in group)
  9. {
  10. Console.WriteLine("{0} -- {1} -- {2} -- {3}", _student.id, _student.name, _student.age, _student.standard);
  11. }
  12. Console.WriteLine("---------------------------------------------");
  13. }
  14. Console.ReadKey();
Output: The output will be the same as in Example 1.

We need to use anonymous types to sort the elements within the group. The following example will show how to do that:

  1. List<student> studentlist = student.getstudents();
  2. //result order by elements
  3. var resultorderbyelement = from stu in studentlist
  4. group stu by stu.standard
  5. into egroup
  6. orderby egroup.Key
  7. select new
  8. {
  9. Key = egroup.Key,
  10. studentobj = egroup.OrderBy(g => g.name)
  11. };
  12. foreach (var group in resultorderbyelement)
  13. {
  14. Console.WriteLine("class - {0} ", group.Key);
  15. Console.WriteLine("{0} -- {1} -- {2} -- {3}", "ID", "NAME", "AGE", "CLASS");
  16. foreach (var _student in group.studentobj)
  17. {
  18. Console.WriteLine("{0} -- {1} -- {2} -- {3}", _student.id, _student.name, _student.age, _student.standard);
  19. }
  20. Console.WriteLine("---------------------------------------------");
  21. }
  22. Console.ReadKey();
Output

imageclass

This example works the same as Example 3 but uses a lambda to do the job.

  1. List<student> studentlist = student.getstudents();
  2. //result using lamba and sort elements by name
  3. var resultlambaorderbyelement = studentlist
  4. .GroupBy(stu => stu.standard)
  5. .OrderBy(stu => stu.Key)
  6. .Select(g => new { Key = g.Key, studentobj = g.OrderBy(y => y.name) });
  7. foreach (var group in resultlambaorderbyelement)
  8. {
  9. Console.WriteLine("class - {0} ", group.Key);
  10. Console.WriteLine("{0} -- {1} -- {2} -- {3}", "ID", "NAME", "AGE", "CLASS");
  11. foreach (var _student in group.studentobj)
  12. {
  13. Console.WriteLine("{0} -- {1} -- {2} -- {3}", _student.id, _student.name, _student.age, _student.standard);
  14. }
  15. Console.WriteLine("---------------------------------------------");
  16. }
  17. Console.ReadKey();
Output: The output will be the same as Example 3.

Group By: Multiple keys

This example will group students first by standard (class) and then by their age.

  1. var resultmultiplekey = from stu in studentlist
  2. group stu by new { stu.standard, stu.age }
  3. into egroup
  4. orderby egroup.Key.standard, egroup.Key.age
  5. select egroup;
  6. foreach (var group in resultmultiplekey)
  7. {
  8. Console.WriteLine("class - {0} -- age - {1} -- Count of items - {2}", group.Key.standard, group.Key.age, group.Count());
  9. Console.WriteLine("{0} -- {1} -- {2} -- {3}", "ID", "NAME", "AGE", "CLASS");
  10. foreach (var _student in group)
  11. {
  12. Console.WriteLine("{0} -- {1} -- {2} -- {3}", _student.id, _student.name, _student.age, _student.standard);
  13. }
  14. Console.WriteLine("---------------------------------------------");
  15. }
  16. Console.ReadKey();
Output

class
  1. This example is same as example 1 but uses lambda syntax to do the job
  2. //result using lamba
  3. var resultmultiplekeylamba = studentlist
  4. .GroupBy(stu => new{stu.standard, stu.age})
  5. .OrderBy(g=> g.Key.standard).ThenBy(y=> y.Key.age);
  6. foreach (var group in resultmultiplekeylamba)
  7. {
  8. Console.WriteLine("class - {0} -- age - {1} -- Count of items - {2}", group.Key.standard, group.Key.age, group.Count());
  9. Console.WriteLine("{0} -- {1} -- {2} -- {3}", "ID", "NAME", "AGE", "CLASS");
  10. foreach (var _student in group)
  11. {
  12. Console.WriteLine("{0} -- {1} -- {2} -- {3}", _student.id, _student.name, _student.age, _student.standard);
  13. }
  14. Console.WriteLine("---------------------------------------------");
  15. }
  16. Console.ReadKey();
Output: The output will be the same as Example 1.

Again, in this example we will use anonymous types to sort the results of Examples 1 and 2 by the student's name.

  1. var resultmutiplekeyorderbyelement = from stu in studentlist
  2. group stu by new { stu.standard, stu.age }
  3. into egroup
  4. orderby egroup.Key.standard, egroup.Key.age
  5. select new
  6. {
  7. standardkey = egroup.Key.standard,
  8. agekey = egroup.Key.age,
  9. studentobj = egroup.OrderBy(y => y.standard).ThenBy(y => y.name)
  10. };
  11. foreach (var group in resultmutiplekeyorderbyelement)
  12. {
  13. Console.WriteLine("class - {0} -- age - {1} -- Count of items - {2}", group.standardkey, group.agekey, group.studentobj.Count());
  14. Console.WriteLine("{0} -- {1} -- {2} -- {3}", "ID", "NAME", "AGE", "CLASS");
  15. foreach (var _student in group.studentobj)
  16. {
  17. Console.WriteLine("{0} -- {1} -- {2} -- {3}", _student.id, _student.name, _student.age, _student.standard);
  18. }
  19. Console.WriteLine("---------------------------------------------");
  20. }
  21. Console.ReadKey();
Output

image

This example does the same as Example 3 but uses a lambda to do the job.
//result using lamba with multiple key and sort elements by name.

  1. var resultmutiplekeylambaorderbyelement = studentlist
  2. .GroupBy(stu => new{stu.standard, stu.age})
  3. .OrderBy(g => g.Key.standard).ThenBy(y=> y.Key.age)
  4. .Select(g => new { standardkey = g.Key.standard, agekey = g.Key.age, studentobj = g.OrderBy(y => y.name) });
  5. foreach (var group in resultmutiplekeylambaorderbyelement)
  6. {
  7. Console.WriteLine("class - {0} -- age - {1} -- Count of items - {2}", group.standardkey, group.agekey, group.studentobj.Count());
  8. Console.WriteLine("{0} -- {1} -- {2} -- {3}", "ID", "NAME", "AGE", "CLASS");
  9. foreach (var _student in group.studentobj)
  10. {
  11. Console.WriteLine("{0} -- {1} -- {2} -- {3}", _student.id, _student.name, _student.age, _student.standard);
  12. }
  13. Console.WriteLine("---------------------------------------------");
  14. }
  15. Console.ReadKey();
Output: the Output will be the same as in Example 3.