LINQ GroupBy Method with Multiple Keys

LINQ GroupBy Method with Multiple Keys in C#

In this article, I will discuss the LINQ GroupBy Method with Multiple Keys in C# with Examples. Please read our previous article before proceeding to this article, where we discussed the Linq GroupBy Method in C# with Examples. As part of this article, we will discuss the following pointers.

  1. Why do we need to group the data based on Multiple Keys?
  2. How to use the LINQ GroupBy Method with Multiple Keys in C#?
  3. Multiple Examples using both Method and Query Syntax.
Why do we need to group the data based on Multiple Keys?

It is a common requirement in real-time applications to group the data based on multiple keys. In LINQ (Language-Integrated Query), you can use the GroupBy method to group elements in a collection based on one or more keys.

The GroupBy Method in LINQ (Language Integrated Query) allows us to group sequence elements based on a specified key. When you need to group by multiple keys, you can use an anonymous type or a tuple to encapsulate these keys. This approach is useful when organizing data based on a combination of properties.

LINQ GroupBy Method in C# with Examples using Multiple Keys

Let us understand how to use the LINQ GroupBy Method in C# with Multiple Keys. We will use the following Student class to understand the GroupBy Method with Multiple Keys. So, create a class file named Student.cs and copy and paste the following code. This class has five properties: ID, Name, Gender, Branch, and Age. This class also has one method called GetStudents(), which returns a list of all students and will be our data source.

using System.Collections.Generic;
namespace GroupByDemo
{
    public class Student
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public string Gender { get; set; }
        public string Barnch { get; set; }
        public int Age { get; set; }

        public static List<Student> GetStudents()
        {
            return new List<Student>()
            {
                new Student { ID = 1001, Name = "Preety", Gender = "Female", Barnch = "CSE", Age = 20 },
                new Student { ID = 1002, Name = "Snurag", Gender = "Male", Barnch = "ETC", Age = 21  },
                new Student { ID = 1003, Name = "Pranaya", Gender = "Male", Barnch = "CSE", Age = 21  },
                new Student { ID = 1004, Name = "Anurag", Gender = "Male", Barnch = "CSE", Age = 20  },
                new Student { ID = 1005, Name = "Hina", Gender = "Female", Barnch = "ETC", Age = 20 },
                new Student { ID = 1006, Name = "Priyanka", Gender = "Female", Barnch = "CSE", Age = 21 },
                new Student { ID = 1007, Name = "santosh", Gender = "Male", Barnch = "CSE", Age = 22  },
                new Student { ID = 1008, Name = "Tina", Gender = "Female", Barnch = "CSE", Age = 20  },
                new Student { ID = 1009, Name = "Celina", Gender = "Female", Barnch = "ETC", Age = 22 },
                new Student { ID = 1010, Name = "Sambit", Gender = "Male",Barnch = "ETC", Age = 21 }
            };
        }
    }
}
Example to Understand Grouping Students Based on Multiple Keys in C#

Our requirement is to group the students based on Branch and gender. First, we need to group the students by Branch, and then we need to group the students by Gender. Also, we need to sort the students in each group by Name in Ascending order. For a better understanding, please look at the following example, which exactly does the same thing. The following example code is self-explained, so please go through the comment lines. 

using System;
using System.Linq;

namespace GroupByDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            //Using Method Syntax
            var GroupByMultipleKeysMS = Student.GetStudents()
                .GroupBy(x => new { x.Barnch, x.Gender })
                .Select(g => new
                {
                    Branch = g.Key.Barnch,
                    Gender = g.Key.Gender,
                    Students = g.OrderBy(x => x.Name)
                }); ;

            //Using Query Syntax
            var GroupByMultipleKeysQS = (from std in Student.GetStudents()
                                         group std by new
                                         {
                                             std.Barnch,
                                             std.Gender
                                         } into stdGroup
                                         select new
                                         {
                                             Branch = stdGroup.Key.Barnch,
                                             Gender = stdGroup.Key.Gender,
                                             //Sort the Students of Each group by Name in Ascending Order
                                             Students = stdGroup.OrderBy(x => x.Name)
                                         });

            //It will iterate through each group
            foreach (var group in GroupByMultipleKeysQS)
            {
                Console.WriteLine($"Barnch : {group.Branch} Gender: {group.Gender} No of Students = {group.Students.Count()}");
                //It will iterate through each item of a group
                foreach (var student in group.Students)
                {
                    Console.WriteLine($"  ID: {student.ID}, Name: {student.Name}, Age: {student.Age} ");
                }
                Console.WriteLine();
            }

            Console.Read();
        }
    }
}

When you run the above code, you will get the following output.

Example to Understand Grouping Students Based on Multiple Keys in C#

Grouping Students Based on the Branch and Gender along with OrderBy Method

Our requirement is to group the students based on Branch and gender. First, we need to group the students by Branch in Descending Order, and then we need to group the students by Gender in Ascending order on each branch group. Finally, the students in each group need to be sorted by their names in Ascending Order. For a better understanding, please look at the following example, which exactly does the same thing. The following example code is self-explained, so please go through the comment lines. 

using System;
using System.Linq;
namespace GroupByDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            //Using Method Syntax
            var GroupByMultipleKeysMS = Student.GetStudents()
                //Group the Students first by Branch and then Gender
                                        .GroupBy(x => new { x.Barnch, x.Gender })
                                        //Sort Each Group in Descending Order Based on Branch
                                        .OrderByDescending(g => g.Key.Barnch)
                                        //Then Sort Each Branch Group in Ascending Order Based on Gender
                                        .ThenBy(g => g.Key.Gender)
                                        //Project the Result to an Annonymous Type
                                        .Select(g => new
                                        {
                                            Branch = g.Key.Barnch,
                                            Gender = g.Key.Gender,
                                            //Sort the Students of Each group by Name in Ascending Order
                                            Students = g.OrderBy(x => x.Name)
                                        });
            //Using Query Syntax
            var GroupByMultipleKeysQS = from student in Student.GetStudents()
                                        //Group the Students by Branch and then Gender and Store the
                                        //Result into a variable
                                        group student by new
                                        {
                                            student.Barnch,
                                            student.Gender
                                        } into stdGroup

                                        //Then Sort the group by Barnch Descending and Gender Ascending Order
                                        orderby stdGroup.Key.Barnch descending,
                                                stdGroup.Key.Gender ascending
                                        
                                        //Project the Result to an Annonymous Type
                                        select new
                                        {
                                            Branch = stdGroup.Key.Barnch,
                                            Gender = stdGroup.Key.Gender,

                                            //Sort the Students of Each group by Name in Ascending Order
                                            Students = stdGroup.OrderBy(x => x.Name)
                                        };

            //It will iterate through each group
            foreach (var group in GroupByMultipleKeysQS)
            {
                Console.WriteLine($"Barnch : {group.Branch} Gender: {group.Gender} No of Students = {group.Students.Count()}");
                //It will iterate through each item of a group
                foreach (var student in group.Students)
                {
                    Console.WriteLine($"  ID: {student.ID}, Name: {student.Name}, Age: {student.Age} ");
                }
                Console.WriteLine();
            }
            Console.Read();
        }
    }
}

You will get the following output when you run the above application code.

LINQ GroupBy Method with Multiple Keys in C# with Examples

We have projected the result to an anonymous type in the above example. You can also create a new type with the required properties and then project the result to that new type. Let us understand this. First, create a class file named StudentGroupByBranchGender.cs, and copy and paste the following code.

using System.Collections.Generic;
namespace GroupByDemo
{
    public class StudentGroupByBranchGender
    {
        public string Branch { get; set; }
        public string Gender { get; set; }
        public List<Student> Students { get; set; }
    }
}

With the above changes in place, now modify the Main method of the Program class as follows. Here, we are projecting the result into the newly created StudentGroupByBranchGender type instead of the anonymous one. 

using System;
using System.Linq;
namespace GroupByDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            //Using Method Syntax
            var GroupByMultipleKeysMS = Student.GetStudents()
                //Group the Students first by Branch and then Gender
                                        .GroupBy(x => new { x.Barnch, x.Gender })
                                        //Sort Each Group in Descending Order Based on Branch
                                        .OrderByDescending(g => g.Key.Barnch)
                                        //Then Sort Each Branch Group in Ascending Order Based on Gender
                                        .ThenBy(g => g.Key.Gender)
                                        //Project the Result to StudentGroupByBranchGender Type
                                        .Select(g => new StudentGroupByBranchGender
                                        {
                                            Branch = g.Key.Barnch,
                                            Gender = g.Key.Gender,
                                            //Sort the Students of Each group by Name in Ascending Order
                                            Students = g.OrderBy(x => x.Name).ToList()
                                        });
            //Using Query Syntax
            var GroupByMultipleKeysQS = from student in Student.GetStudents()
                                        //Group the Students by Branch and then Gender and Store the
                                        //Result into a variable
                                        group student by new
                                        {
                                            student.Barnch,
                                            student.Gender
                                        } into stdGroup

                                        //Then Sort the group by Barnch Descending and Gender Ascending Order
                                        orderby stdGroup.Key.Barnch descending,
                                                stdGroup.Key.Gender ascending

                                        //Project the Result to StudentGroupByBranchGender Type
                                        select new StudentGroupByBranchGender
                                        {
                                            Branch = stdGroup.Key.Barnch,
                                            Gender = stdGroup.Key.Gender,
                                            //Sort the Students of Each group by Name in Ascending Order
                                            Students = stdGroup.OrderBy(x => x.Name).ToList()
                                        };

            //It will iterate through each group
            foreach (StudentGroupByBranchGender group in GroupByMultipleKeysQS)
            {
                Console.WriteLine($"Barnch : {group.Branch} Gender: {group.Gender} No of Students = {group.Students.Count()}");
                //It will iterate through each item of a group
                foreach (var student in group.Students)
                {
                    Console.WriteLine($"  ID: {student.ID}, Name: {student.Name}, Age: {student.Age} ");
                }
                Console.WriteLine();
            }
            Console.Read();
        }
    }
}

Now, run the application code, and you will get the following output as expected.

LINQ GroupBy Method with Multiple Keys in C#

Different Ways to use GroupBy method with multiple keys in C#

Here is how you can use the GroupBy method with multiple keys in C#:

Using Anonymous Types:

The most common way to group by multiple keys is by using an anonymous type, which includes all the keys you want to group by.

var groupedResult = context.YourEntities
    .GroupBy(e => new { e.Key1, e.Key2 })
    .Select(group => new
    {
        Key1 = group.Key.Key1,
        Key2 = group.Key.Key2,
        Count = group.Count(),
        Items = group.ToList() // Or any aggregation/operation you want
    });

 

In this example, Key1 and Key2 are the properties we want to group our entities. The resulting groupedResult will be a collection of anonymous objects, each representing a unique combination of Key1 and Key2.

Using Tuple (C# 7.0 and later):

You can also use tuples to group by multiple keys, which can be more concise.

var groupedResult = context.YourEntities
    .GroupBy(e => (e.Key1, e.Key2))
    .Select(group => new
    {
        group.Key.Key1,
        group.Key.Key2,
        Count = group.Count(),
        Items = group.ToList()
    });

The GroupBy now uses a tuple (e.Key1, e.Key2) for grouping. The tuple provides a convenient syntax and is especially useful if you plan to use the keys later.

Using a Custom Class or Struct:

You can define a custom class or struct if you need more control or want to reuse the key type elsewhere.

public class GroupingKey
{
    public int Key1 { get; set; }
    public string Key2 { get; set; }
    
    // Depending on your needs, you might also need to override Equals() and GetHashCode()
}

var groupedResult = context.YourEntities
    .GroupBy(e => new GroupingKey { Key1 = e.Key1, Key2 = e.Key2 })
    .Select(group => new
    {
        group.Key.Key1,
        group.Key.Key2,
        Count = group.Count(),
        Items = group.ToList()
    });

A custom class can be beneficial when you have complex keys or want to perform additional logic within the key.

Using Query Syntax:

You can also group by multiple keys using query syntax, which some find more readable:

var groupedResult = from e in context.YourEntities
                    group e by new { e.Key1, e.Key2 } into g
                    select new
                    {
                        g.Key.Key1,
                        g.Key.Key2,
                        Count = g.Count(),
                        Items = g.ToList()
                    };

Query syntax is often preferred for more complex queries as it can be more verbose and easier to understand at a glance.

Regardless of your chosen method, grouping by multiple keys allows you to perform complex queries and aggregations in LINQ, leveraging the power of C#’s syntax to keep your code readable and maintainable.

When to Use the LINQ GroupBy Method with Multiple Keys?

The GroupBy method in LINQ is a versatile tool for organizing data into groups based on some shared attributes. Here are scenarios when you might use GroupBy with multiple keys:

  • Complex Data Structures: When working with complex data with multiple fields, grouping by multiple keys allows us to create nested groupings based on different attributes. This can be useful for hierarchical data or when analyzing data across multiple dimensions.
  • Multi-Level Analysis: If your analysis requires examining data at different levels or based on multiple criteria, grouping by several keys can simplify this process. For example, in a sales dataset, you might want to group sales data by region and product category.
  • Cross-Sectional Data Analysis: Using multiple keys in GroupBy can effectively analyze data across different cross-sections. For instance, if you are analyzing a survey, you might group responses by age group and then by gender.
  • Comparative Analysis: If you compare data sets that vary across more than one variable, grouping by multiple keys can provide a clearer comparison. For example, comparing academic performance by both grade level and subject area.
  • Efficiency in Data Aggregation: Grouping by multiple keys can be more efficient than performing multiple single-key groupings and combining them. It simplifies the code and can improve performance, especially with large datasets.
  • Data Segmentation for Business Intelligence: In business intelligence and reporting, segmenting data by multiple criteria (like geographic location, time period, and customer segment) is common to get nuanced insights.

In the next article, I will discuss the LINQ ToLookup Method in C# with Examples. In this article, I explain using the LINQ GroupBy Method with Multiple Keys in C# with Examples. I hope you enjoy this article and understand the need and use of the LINQ GroupBy with Multiple Keys in C#.

3 thoughts on “LINQ GroupBy Method with Multiple Keys”

Leave a Reply

Your email address will not be published. Required fields are marked *