How To Use LINQ GroupBy Method

Cesar Aguirre - Jul 6 '22 - - Dev Community

I originally published this post on my blog a couple of weeks ago. It's part of a post series about LINQ.


Let's take a deeper look at one of the most common LINQ methods: GroupBy.

The GroupBy method groups the elements of a collection based on a grouping key. This method returns a collection of "groups" or "buckets" organized by that key.

The GroupBy method receives as a parameter a delegate with the property to use as a key when grouping elements.

For example, let's group our catalog of movies by rating.

var movies = new List<Movie>
{
    new Movie("Titanic", 1998, 4.5f),
    new Movie("The Fifth Element", 1997, 4.6f),
    new Movie("Terminator 2", 1991, 4.7f),
    new Movie("Avatar", 2009, 5),
    new Movie("Platoon", 1986, 4),
    new Movie("My Neighbor Totoro", 1988, 5)
};

// Group our catalog of movies based on their rating
var groupedByRating = movies.GroupBy(movie => movie.Rating);
//                           👆👆👆

foreach (var group in groupedByRating)
{
    // Each group or bucket has a Key property  
    Console.WriteLine($"Rating: {group.Key}");

    foreach (var movie in group)
    {
        Console.WriteLine($"{movie.Name}");
    }
    Console.WriteLine();
}
// Output:
//Rating: 4.5
//Titanic
//
//Rating: 4.6
//The Fifth Element
//
//Rating: 4.7
//Terminator 2
//
//Rating: 5
//Avatar
//My Neighbor Totoro
//
//Rating: 4
//Platoon

record Movie(string Name, int ReleaseYear, float Rating);
Enter fullscreen mode Exit fullscreen mode

We used Top-level statements, records and implicit usings statements. All boilerplate code is gone!

Also, to group our catalog of movies, we used movie => movie.Rating as the parameter for the GroupBy method.

Magazine stand

We're grouping films, not magazines. Photo by Charisse Kenion on Unsplash

How to transform every group

Apart from grouping collections by a key, the GroupBy method has another overload to transform each group or bucket of items.

Let's change the previous example to count the movies with the same rating.

var movies = new List<Movie>
{
    new Movie("Titanic", 1998, 4.5f),
    new Movie("The Fifth Element", 1997, 4.6f),
    new Movie("Terminator 2", 1991, 4.7f),
    new Movie("Avatar", 2009, 5),
    new Movie("Platoon", 1986, 4),
    new Movie("My Neighbor Totoro", 1988, 5)
};

// Transform every group into a RatingCount type
var countByRating = movies.GroupBy(movie => movie.Rating,
                    (rating, movies) => new RatingCount(rating, movies.Count());
//                  👆👆👆

foreach (var group in countByRating)
{
    Console.WriteLine($"{group.Rating}: [{group.Count}]");
}
// Output:
//4.5: [1]
//4.6: [1]
//4.7: [1]
//5: [2]
//4: [1]

record Movie(string Name, int ReleaseYear, float Rating);
record RatingCount(float Rating, int Count);
Enter fullscreen mode Exit fullscreen mode

This time, we passed a second parameter to the GroupBy method.

The first parameter was still the grouping key, as usual. But, the second one was a delegate that received the grouping key and the elements of each group. We named the two parameters: rating and movies.

With the ratings and the movies per rating, we transformed every group of movies into a new object, RatingCount.

Since we wanted to count the movies with the same rating, we used another LINQ method: Count.

How to group by more than one property

We've used Rating as the grouping key. But we can group the elements of a collection by more than one grouping property.

With the GroupBy method, to group a collection by more than one property, use a custom object as the grouping key.

For example, to group our catalog of movies by release year and reating, we can write a LINQ query like this,

var groupByReleasedYearAndRating = movies.GroupBy(movie => new
{
    movie.ReleaseYear,
    movie.Rating
});
Enter fullscreen mode Exit fullscreen mode

Then, the Key property would be an object, instead of a primitive value. It means, we can access both the ReleaseYear and the Rating of each group.

For example,

var groupByReleasedYearAndRating = movies.GroupBy(movie => new { movie.ReleaseYear, movie.Rating });

foreach (var group in groupByReleasedYearAndRating)
{
    var groupingKey = group.Key;
    var releaseYear = groupingKey.ReleaseYear;
    //                👆👆👆
    var rating = groupingKey.Rating;
    //           👆👆👆

    // Do something with the releaseYear and rating...🤖
    foreach (var movie in group)
    {
        // Do something with each movie in the group...🤖
    }
}
Enter fullscreen mode Exit fullscreen mode

Voilà! That's the GroupBy method. It creates groups or buckets with the elements of a collection and transforms each group.

If you noticed the output of our previous examples, the GroupBy method grouped the elements without sorting them. For that, we would need the OrderBy method.


Want to write more expressive code for collections? Join my Udemy course, Getting Started with LINQ, and master everything you need to work productively with LINQ — all in less than two hours!

Happy coding!

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .