How to use LINQ GroupBy method?
Tags: csharp, beginners, dotnet, tutorial
Published: 2022-07-06 16:23:15

_I originally published this post on [my blog](https://canro91.github.io/2022/05/30/HowToUseLinqGroupBy/) 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](https://canro91.github.io/2022/05/16/LINQMethodsInPictures/). 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](https://canro91.github.io/2019/03/22/WhatTheFuncAction/) with the property to use as a key when grouping elements.

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

```csharp
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);
```

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.

<figure>
<img src="https://source.unsplash.com/8hJQKRIQZMY/600x400" alt="Magazine stand" />

<figcaption>books.GroupBy(book => book.Category)...Photo by <a href="https://unsplash.com/@cristina_gottardi?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Cristina Gottardi</a> on <a href="https://unsplash.com/?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Unsplash</a></figcaption>
</figure>

## 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.

```csharp
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);
```

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,

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

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,

```csharp
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
    }
}
```

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.

***

_Hey! I'm Cesar, a software engineer and lifelong learner. If you want to learn more about this subject, check my course [Getting Started with LINQ](https://bit.ly/csarag-linq-course) on Educative where I cover other LINQ methods in depth._

_Happy coding!_