Summary: in this tutorial, you’ll learn how to use the LINQ GroupBy()
method to group the elements of a sequence based on a key.
The GroupBy()
method groups elements in a sequence based on a specified key. The method returns a sequence of groups, where each element implements the IGrouping(TKey, TElement>
interface.
The
method has several overloads, and each has a specific purpose. We’ll introduce to you some of the GroupBy()
overloads with examples.GroupBy()
A simple LINQ GroupBy() method
Here’s the syntax of the GroupBy()
method:
IGrouping<TKey,TElement> GroupBy<TSource, TKey>(
IEnumerable<TSource> source,
Func<TSource, TKey> keySelector
);
Code language: C# (cs)
In this syntax:
TSource
is the type of elements of the source sequence.TKey
is the key returned by thekeySelector
function.
is the type of elements in theTElement
IGrouping<TKey, TElement>
.source
is the input sequence that has theIEnumerable<TSource>
.keySelector
is a function that selects the key for each element.elementSelector
is a function that maps each element to an element in theIGrouping
<TKey
,TElement
>.
The GroupBy()
by method returns a sequence of elements with the type of IGrouping<TKey, TElement>
.
The following example uses the GroupBy()
method to group a list of students into groups specified by courses of the students:
class Student
{
public string? Name { get; set; }
public string? Course { get; set; }
public int Age { get; set; }
}
class Program
{
public static void Main(string[] args)
{
// Create a list of students
var students = new List<Student>()
{
new Student { Name = "John", Course = "C#", Age = 25 },
new Student { Name = "Jane", Course = "C#", Age = 22 },
new Student { Name = "Bob", Course = "Javascript", Age = 20 },
new Student { Name = "Alice", Course = "Javascript", Age = 21 }
};
// Group the students by course
var groups = students.GroupBy(s => s.Course);
// Show the groups
foreach (var group in groups)
{
Console.WriteLine(group.Key + ":");
foreach (var student in group)
{
Console.WriteLine("- " + student.Name + " (" + student.Age + ")");
}
Console.WriteLine();
}
}
}
Code language: C# (cs)
Output:
C#:
- John (25)
- Jane (22)
Javascript:
- Bob (20)
- Alice (21)
Code language: C# (cs)
How it works.
First, define a Student
class that has three properties Name
, Course
, and Age
:
class Student
{
public string? Name { get; set; }
public string? Course { get; set; }
public int Age { get; set; }
}
Code language: C# (cs)
Second, create a list that has four Student
objects:
var students = new List<Student>()
{
new Student { Name = "John", Course = "C#", Age = 25 },
new Student { Name = "Jane", Course = "C#", Age = 22 },
new Student { Name = "Bob", Course = "Javascript", Age = 20 },
new Student { Name = "Alice", Course = "Javascript", Age = 21 }
};
Code language: C# (cs)
Third, use the GroupBy()
method to group the students by courses:
var groups = students.GroupBy(s => s.Course);
Code language: C# (cs)
Finally, show the groups to the Console:
foreach (var group in groups)
{
Console.WriteLine(group.Key + ":");
foreach (var student in group)
{
Console.WriteLine("- " + student.Name + " (" + student.Age + ")");
}
Console.WriteLine();
}
Code language: C# (cs)
Using the LINQ GroupBy() method with an element selector
The following overload of the GroupBy()
method has a second delegate that allows you to select the elements of the groups:
IGrouping<TKey,TElement> GroupBy<TSource, TKey, TElement>(
IEnumerable<TSource> source,
Func<TSource, TKey> keySelector,
Func<TSource, TElement> elementSelector
);
Code language: C# (cs)
For example:
using static System.Console;
class Student
{
public string? Name { get; set; }
public string? Course { get; set; }
public int Age { get; set; }
}
class Program
{
public static void Main(string[] args)
{
// Create a list of students
var students = new List<Student>()
{
new Student { Name = "John", Course = "C#", Age = 25 },
new Student { Name = "Jane", Course = "C#", Age = 22 },
new Student { Name = "Bob", Course = "Javascript", Age = 20 },
new Student { Name = "Alice", Course = "Javascript", Age = 21 }
};
// Group the students by course
var groups = students.GroupBy(s => s.Course, s=> s.Name);
// Show the groups
foreach (var group in groups)
{
WriteLine($"{group.Key}:");
foreach (var name in group)
{
WriteLine($"- {name}");
}
WriteLine();
}
}
}
Code language: C# (cs)
Output:
C#:
- John
- Jane
Javascript:
- Bob
- Alice
Code language: C# (cs)
In this example, we use the elementSelector
function to select the elements for each group. More specifically, we select the name of each student as the element of the result sequence.
Using the LINQ GroupBy() method with an equality comparer
The following overload of the GroupBy()
method allows you to specify an instance of IEqualityComparer<TKey>
to compare keys for equality:
IGrouping<TKey,TElement> GroupBy<TSource, TKey, TElement>(
IEnumerable<TSource> source,
Func<TSource, TKey> keySelector,
Func<TSource, TElement> elementSelector,
IEqualityComparer<TKey>? comparer
);
Code language: C# (cs)
This overload is useful when you want to have a specific equality comparer that fits your scenario.
For example, the following uses the GroupBy()
method with a CourseComparer that compares two course case-insensitively:
using static System.Console;
class Student
{
public string? Name { get; set; }
public string? Course { get; set; }
public int Age { get; set; }
}
class CourseComparer : IEqualityComparer<string?>
{
public bool Equals(string? x, string? y)
{
if (x == null || y == null)
return false;
return x.ToLower() == y.ToLower();
}
public int GetHashCode(string obj)
{
return obj.ToLower().GetHashCode();
}
}
class Program
{
public static void Main(string[] args)
{
// Create a list of students
var students = new List<Student>()
{
new Student { Name = "John", Course = "C#", Age = 25 },
new Student { Name = "Jane", Course = "c#", Age = 22 },
new Student { Name = "Bob", Course = "Javascript", Age = 20 },
new Student { Name = "Alice", Course = "JAVASCRIPT", Age = 21 }
};
var groups = students.GroupBy(s => s.Course, new CourseComparer());
// Display the groups
foreach (var group in groups)
{
WriteLine($"{group.Key}:");
foreach (var student in group)
{
WriteLine($"- {student.Name} ({student.Age})");
}
WriteLine();
}
}
}
Code language: C# (cs)
Output:
C#:
- John (25)
- Jane (22)
Javascript:
- Bob (20)
- Alice (21)
Code language: C# (cs)
In this example, the course names are not standardized. Some courses are in upper case while others are not:
var students = new List<Student>()
{
new Student { Name = "John", Course = "C#", Age = 25 },
new Student { Name = "Jane", Course = "c#", Age = 22 },
new Student { Name = "Bob", Course = "Javascript", Age = 20 },
new Student { Name = "Alice", Course = "JAVASCRIPT", Age = 21 }
};
Code language: C# (cs)
The CourseComparer
class compares two courses case-insensitively by converting them to lowercase before comparison:
class CourseComparer : IEqualityComparer<string?>
{
public bool Equals(string? x, string? y)
{
if (x == null || y == null)
return false;
return x.ToLower() == y.ToLower();
}
public int GetHashCode(string obj)
{
return obj.ToLower().GetHashCode();
}
}
Code language: C# (cs)
The GroupBy()
method uses an instance of the CourseComparer
to group the students by the course names:
var groups = students.GroupBy(s => s.Course, new CourseComparer());
Code language: C# (cs)
Summary
- Use the LINQ
GroupBy()
method to group elements in a sequence into groups by a specified key.