GroupBy Operations

Vaibhav • September 11, 2025

As your LINQ skills grow, you’ll often find yourself needing to categorize data - not just filter or sort it. That’s where GroupBy comes in. It’s one of the most powerful and expressive tools in LINQ, allowing you to organize elements into logical buckets based on a key. Whether you’re grouping students by grade, products by category, or logs by date, GroupBy helps you structure data for deeper analysis and cleaner presentation.

What is Grouping?

Grouping is the process of partitioning a collection into subsets where each subset shares a common characteristic - the grouping key. In LINQ, this is done using the GroupBy method in method syntax or the group ... by clause in query syntax. Each group is represented as an IGrouping<TKey, TElement>, which contains the key and the elements that belong to that group.

List fruits = new List { "apple", "apricot", "banana", "blueberry", "cherry" };

var grouped = from fruit in fruits
              group fruit by fruit[0];

This query groups fruits by their first letter. The result is a sequence of groups - one for “a”, one for “b”, and one for “c”. Each group contains the fruits that start with that letter.

Using GroupBy in Method Syntax

Method syntax uses the GroupBy method, which takes a lambda expression to define the key selector. The result is a collection of groupings.

var grouped = fruits.GroupBy(f => f[0]);

This is equivalent to the query syntax example above. Each group has a Key property (the first letter) and a sequence of elements (the fruits).

Iterating Over Groups

Once you have a grouped result, you can iterate over it using foreach. Each group behaves like a mini collection.

foreach (var group in grouped)
{
    Console.WriteLine($"Group: {group.Key}");
    foreach (var fruit in group)
    {
        Console.WriteLine($"  {fruit}");
    }
}

This prints each group’s key followed by its elements. It’s a common pattern for displaying grouped data in reports or dashboards.

Grouping Custom Objects

Grouping becomes even more powerful when applied to custom types. Suppose you have a list of products with categories:

class Product
{
    public string Name { get; set; }
    public string Category { get; set; }
}

List products = new List
{
    new Product { Name = "Laptop", Category = "Electronics" },
    new Product { Name = "Tablet", Category = "Electronics" },
    new Product { Name = "Apple", Category = "Fruit" },
    new Product { Name = "Banana", Category = "Fruit" }
};

var grouped = products.GroupBy(p => p.Category);

This groups products by their category. You’ll get two groups: one for “Electronics” and one for “Fruit”. Each group contains the relevant products.

Projecting Group Results

You can shape the output of a group using select in query syntax or Select in method syntax. This lets you create summaries or custom views.

var summaries = from group in grouped
                select new { Category = group.Key, Count = group.Count() };

This query creates an anonymous object for each group, showing the category and the number of products in that category. It’s useful for analytics and dashboards.

Flattening Groups

Sometimes you want to flatten grouped data back into a single sequence, possibly with additional context. You can do this using SelectMany.

var flattened = grouped.SelectMany(g => g.Select(p => new { g.Key, p.Name }));

This creates a flat list of anonymous objects, each containing the group key and the product name. It’s helpful when you need to display grouped data in a table or export format.

Grouping with Computed Keys

You’re not limited to simple properties as keys. You can group by computed values, such as string length or date parts.

var groupedByLength = fruits.GroupBy(f => f.Length);

This groups fruits by the number of characters in their name. You’ll get groups for lengths like 5, 6, 9, etc.

Using GroupBy with Multiple Keys

LINQ doesn’t support multi-key grouping directly, but you can simulate it using anonymous types or tuples.

var grouped = products.GroupBy(p => new { p.Category, Length = p.Name.Length });

This groups products by both category and name length. Each group has a composite key with two properties.

Sorting Groups

You can sort groups by their key or by aggregate values. This is useful when displaying grouped data in a meaningful order.

var sortedGroups = grouped.OrderBy(g => g.Key);

This sorts the groups alphabetically by category. You can also sort by g.Count() or other computed metrics.

Filtering Groups

After grouping, you can filter the groups based on their key or contents. This helps you focus on relevant subsets.

var filtered = grouped.Where(g => g.Count() > 1);

This keeps only groups with more than one element. It’s useful for identifying duplicates or popular categories.

Deferred Execution and Grouping

Like most LINQ operations, GroupBy uses deferred execution. The grouping doesn’t happen until you enumerate the result. This allows you to build queries incrementally and efficiently.

Note: If you modify the source collection after defining the query but before enumerating it, the changes will affect the grouping result.

Performance Considerations

Grouping is generally efficient, but it can be memory-intensive for large datasets. Each group is stored in memory, so avoid grouping unnecessarily or on high-cardinality keys.

If you only need aggregate values (like counts or sums), consider using ToLookup or direct aggregation methods instead of full grouping.

Common Mistakes to Avoid

One common mistake is assuming that GroupBy sorts the groups. It doesn’t - the order of groups depends on the source collection. If you need sorted groups, use OrderBy explicitly.

GroupBy returns a sequence of groups, not a dictionary. If you need fast lookup by key, use ToLookup instead.

Using GroupBy with Let in Query Syntax

The let keyword can be used to compute values before grouping. This improves readability and avoids repetition.

var grouped = from fruit in fruits
              let length = fruit.Length
              group fruit by length;

This groups fruits by their length, using let to compute the key. It’s cleaner than repeating fruit.Length in the group by clause.

Summary

GroupBy is a powerful LINQ feature that lets you organize data into meaningful categories. Whether you’re grouping by a simple property, a computed value, or a composite key, LINQ makes it easy to structure your data for analysis and presentation. You can iterate over groups, project summaries, flatten results, and apply sorting or filtering - all with concise, readable syntax. By mastering grouping, you unlock a new level of expressiveness in your LINQ queries and gain deeper insights into your data.

In the next article, we’ll explore Join Operations - how to combine data from multiple collections using LINQ’s relational capabilities.