DEV Community

Cover image for How to use LINQ GroupBy method?
Cesar Aguirre
Cesar Aguirre

Posted on • Updated on • Originally published at canro91.github.io

How to use LINQ GroupBy method?

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. Let's learn how to group the elements of a collection using 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

Notice, 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

books.GroupBy(book => book.Category)...Photo by Cristina Gottardi 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?

In the two previous examples, we used the Rating property 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;
    //                vvvvvvvvvvv
    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.

To learn about LINQ and other methods, check my quick guide to LINQ on my blog. All you need to know to start working with LINQ, in 15 minutes or less.

Hey! I'm Cesar, a software engineer and lifelong learner. If you want to support my work, check my Getting Started with LINQ course on Educative where I cover these and other LINQ methods in depth.

Happy coding!

Discussion (0)