Group by in LINQ: Understanding Grouping with Real Examples
\n\nIf you've ever written queries to collections in C#, you've likely faced the task: "How do I group data?". The topic of group by in LINQ is one of the most popular on Stack Overflow (tens of thousands of views). And this is no coincidence: grouping seems simple only at first glance. In reality, beginners stumble over typical pitfalls: how to select the first record in a group, how to calculate a sum, or how to do nested grouping.
\n\nIn this article, we'll cover the 5 most frequent questions about LINQ GroupBy and provide working answers. Let's go!
\n\n1. How does GroupBy work in LINQ? Basic Syntax
\n\nThe GroupBy method is an analog of the SQL GROUP BY operator. It splits a sequence into groups based on a specified key. The result is a collection of IGrouping<TKey, TElement> objects, where each object contains the key and all elements that fall into that group.
Here's a simple example. Let's say we have a list of students:
\n\npublic class Student\n{\n public string Name { get; set; }\n public string Group { get; set; }\n public int Score { get; set; }\n}\n\nvar students = new List<Student>\n{\n new Student { Name = "Anna", Group = "A", Score = 85 },\n new Student { Name = "Boris", Group = "B", Score = 90 },\n new Student { Name = "Vika", Group = "A", Score = 78 },\n new Student { Name = "Gleb", Group = "B", Score = 92 }\n};\n\nGrouping by group name:
\n\nvar grouped = students.GroupBy(s => s.Group);\n\nforeach (var group in grouped)\n{\n Console.WriteLine($"Group: {group.Key}");\n foreach (var student in group)\n {\n Console.WriteLine($" {student.Name} — {student.Score}");\n }\n}\n\nOutput:
\nGroup: A\n Anna — 85\n Vika — 78\nGroup: B\n Boris — 90\n Gleb — 92\n\nIt's simple. But the devil, as always, is in the details.
\n\n2. How to select the first record from each group?
\n\nThis is the most popular question about group by in LINQ. Let's say we need to get one best student from each group (with the highest score). How to do this?
\n\nThe solution is to combine GroupBy with First() or OrderByDescending:
var bestStudents = students\n .GroupBy(s => s.Group)\n .Select(g => g.OrderByDescending(s => s.Score).First());\n\nforeach (var student in bestStudents)\n{\n Console.WriteLine($"{student.Name} — {student.Group} — {student.Score}");\n}\n\nResult: Anna (85) and Gleb (92). Note: inside Select, we sort the group and take the first element. This is the answer to the question "how to do LINQ group by first".
Important: First() will throw an exception if the group is empty. If that's possible, use FirstOrDefault().
3. How to calculate the sum, count, or average per group?
\n\nOften after grouping, you need not just to iterate over elements, but to get aggregated values. For example, the total score per group or the average score.
\n\nUse Sum, Count, Average:
var groupStats = students\n .GroupBy(s => s.Group)\n .Select(g => new\n {\n Group = g.Key,\n Count = g.Count(),\n TotalScore = g.Sum(s => s.Score),\n AverageScore = g.Average(s => s.Score)\n });\n\nforeach (var stat in groupStats)\n{\n Console.WriteLine($"Group {stat.Group}: {stat.Count} students, total {stat.TotalScore}, average {stat.AverageScore:F2}");\n}\n\nOutput:
\nGroup A: 2 students, total 163, average 81.50\nGroup B: 2 students, total 182, average 91.00\n\nYou can also use Min and Max — in