Grouping refers to the operation of putting data into groups so that the elements in each group share a common attribute. The following illustration shows the results of grouping a sequence of characters. The key for each group is the character.

author: BillWagner ms.author: wiwagn ms.topic: include ms.date: 05/29/2024
The standard query operator methods that group data elements are listed in the following table.
| Method Name | Description | C# Query Expression Syntax | More Information |
|---|---|---|---|
| GroupBy | Groups elements that share a common attribute. An System.Linq.IGrouping object represents each group. | group … by …-or- group … by … into … |
System.Linq.Enumerable.GroupBy System.Linq.Queryable.GroupBy |
| ToLookup | Inserts elements into a System.Linq.Lookup (a one-to-many dictionary) based on a key selector function. | Not applicable. | System.Linq.Enumerable.ToLookup |
The following code example uses the group by clause to group integers in a list according to whether they're even or odd.
sample · csharpdocs/csharp/linq/standard-query-operators/snippets/standard-query-operators/GroupOverview.csOverviewSampleQuerySyntax
namespace StandardQueryOperators;
internal class GroupOverview
{
public static void RunAllSnippets()
{
Console.WriteLine("Group Overview");
OverviewSampleQuery();
Console.WriteLine("Group Overview Method");
OverviewSampleMethod();
}
private static void OverviewSampleQuery()
{
// <OverviewSampleQuerySyntax>
List<int> numbers = [35, 44, 200, 84, 3987, 4, 199, 329, 446, 208];
IEnumerable<IGrouping<int, int>> query = from number in numbers
group number by number % 2;
foreach (var group in query)
{
Console.WriteLine(group.Key == 0 ? "\nEven numbers:" : "\nOdd numbers:");
foreach (int i in group)
{
Console.WriteLine(i);
}
}
// </OverviewSampleQuerySyntax>
}
private static void OverviewSampleMethod()
{
// <OverviewSampleMethodSyntax>
List<int> numbers = [35, 44, 200, 84, 3987, 4, 199, 329, 446, 208];
IEnumerable<IGrouping<int, int>> query = numbers
.GroupBy(number => number % 2);
foreach (var group in query)
{
Console.WriteLine(group.Key == 0 ? "\nEven numbers:" : "\nOdd numbers:");
foreach (int i in group)
{
Console.WriteLine(i);
}
}
// </OverviewSampleMethodSyntax>
}
}The equivalent query using method syntax is shown in the following code:
sample · csharpdocs/csharp/linq/standard-query-operators/snippets/standard-query-operators/GroupOverview.csOverviewSampleMethodSyntax
namespace StandardQueryOperators;
internal class GroupOverview
{
public static void RunAllSnippets()
{
Console.WriteLine("Group Overview");
OverviewSampleQuery();
Console.WriteLine("Group Overview Method");
OverviewSampleMethod();
}
private static void OverviewSampleQuery()
{
// <OverviewSampleQuerySyntax>
List<int> numbers = [35, 44, 200, 84, 3987, 4, 199, 329, 446, 208];
IEnumerable<IGrouping<int, int>> query = from number in numbers
group number by number % 2;
foreach (var group in query)
{
Console.WriteLine(group.Key == 0 ? "\nEven numbers:" : "\nOdd numbers:");
foreach (int i in group)
{
Console.WriteLine(i);
}
}
// </OverviewSampleQuerySyntax>
}
private static void OverviewSampleMethod()
{
// <OverviewSampleMethodSyntax>
List<int> numbers = [35, 44, 200, 84, 3987, 4, 199, 329, 446, 208];
IEnumerable<IGrouping<int, int>> query = numbers
.GroupBy(number => number % 2);
foreach (var group in query)
{
Console.WriteLine(group.Key == 0 ? "\nEven numbers:" : "\nOdd numbers:");
foreach (int i in group)
{
Console.WriteLine(i);
}
}
// </OverviewSampleMethodSyntax>
}
}author: BillWagner ms.author: wiwagn ms.topic: include ms.date: 10/04/2024
sample · csharpdocs/csharp/linq/standard-query-operators/snippets/standard-query-operators/DataSources.csQueryDataSource
namespace StandardQueryOperators;
//<QueryDataSource>
public enum GradeLevel
{
FirstYear = 1,
SecondYear,
ThirdYear,
FourthYear
};
public class Student
{
public required string FirstName { get; init; }
public required string LastName { get; init; }
public required int ID { get; init; }
public required GradeLevel Year { get; init; }
public required List<int> Scores { get; init; }
public required int DepartmentID { get; init; }
}
public class Teacher
{
public required string First { get; init; }
public required string Last { get; init; }
public required int ID { get; init; }
public required string City { get; init; }
}
public class Department
{
public required string Name { get; init; }
public int ID { get; init; }
public required int TeacherID { get; init; }
}
// </QueryDataSource>
public static class Sources
{
public static IEnumerable<Department> Departments =>
[
new() { Name = "English", ID = 1, TeacherID = 901 },
new() { Name = "Mathematics", ID = 2, TeacherID = 965 },
new() { Name = "Engineering", ID = 3, TeacherID = 932 },
new() { Name = "Economics", ID = 4, TeacherID = 945 },
new() { Name = "Physics", ID = 5, TeacherID = 987 },
new() { Name = "Chemistry", ID = 6, TeacherID = 901 }
];
// Create a data source by using a collection initializer.
public static IEnumerable<Student> Students =>
[
new() { FirstName = "Svetlana", LastName = "Omelchenko", DepartmentID = 1, Year = GradeLevel.FirstYear, ID = 111, Scores = [97, 90, 73, 54] },
new() { FirstName = "Claire", LastName = "O'Donnell", DepartmentID = -1, Year = GradeLevel.FirstYear, ID = 112, Scores = [56, 78, 95, 95] },
new() { FirstName = "Sven", LastName = "Mortensen", DepartmentID = 3, Year = GradeLevel.SecondYear, ID = 113, Scores = [61, 52, 48, 72] },
new() { FirstName = "Cesar", LastName = "Garcia", DepartmentID = 4, Year = GradeLevel.SecondYear, ID = 114, Scores = [71, 86, 77, 97] },
new() { FirstName = "Debra", LastName = "Garcia", DepartmentID = 5, Year = GradeLevel.ThirdYear, ID = 115, Scores = [66, 96, 70, 69] },
new() { FirstName = "Fadi", LastName = "Fakhouri", DepartmentID = 6, Year = GradeLevel.ThirdYear, ID = 116, Scores = [93, 72, 62, 65] },
new() { FirstName = "Hanying", LastName = "Feng", DepartmentID = 1, Year = GradeLevel.FourthYear, ID = 117, Scores = [53, 81, 81, 50] },
new() { FirstName = "Hugo", LastName = "Garcia", DepartmentID = 2, Year = GradeLevel.FourthYear, ID = 118, Scores = [68, 91, 60, 51] },
new() { FirstName = "Lance", LastName = "Tucker", DepartmentID = -1, Year = GradeLevel.FirstYear, ID = 119, Scores = [83, 42, 68, 63] },
new() { FirstName = "Terry", LastName = "Adams", DepartmentID = 4, Year = GradeLevel.SecondYear, ID = 120, Scores = [63, 91, 71, 51] },
new() { FirstName = "Eugene", LastName = "Zabokritski", DepartmentID = 5, Year = GradeLevel.ThirdYear, ID = 121, Scores = [56, 40, 73, 75] },
new() { FirstName = "Michael", LastName = "Tucker", DepartmentID = 3, Year = GradeLevel.FourthYear, ID = 122, Scores = [85, 82, 81, 70] },
new() { FirstName = "Mark", LastName = "Johansson", DepartmentID = 1, Year = GradeLevel.FirstYear, ID = 123, Scores = [82, 94, 84, 65] },
new() { FirstName = "Sarah", LastName = "Andersson", DepartmentID = 1, Year = GradeLevel.FirstYear, ID = 124, Scores = [77, 83, 67, 90] },
new() { FirstName = "Christiane", LastName = "Jensen", DepartmentID = 1, Year = GradeLevel.FirstYear, ID = 125, Scores = [88, 57, 65, 87] },
new() { FirstName = "Evgeniya", LastName = "Maslova", DepartmentID = 2, Year = GradeLevel.SecondYear, ID = 126, Scores = [46, 84, 87, 66] },
new() { FirstName = "Innocenty", LastName = "Popov", DepartmentID = 6, Year = GradeLevel.SecondYear, ID = 127, Scores = [92, 45, 88, 60] },
new() { FirstName = "Anna", LastName = "Hedlund", DepartmentID = 2, Year = GradeLevel.SecondYear, ID = 128, Scores = [85, 54, 74, 75] },
new() { FirstName = "Erik", LastName = "Axelsson", DepartmentID = 3, Year = GradeLevel.ThirdYear, ID = 129, Scores = [51, 78, 54, 49] },
new() { FirstName = "Anna", LastName = "Yermolayeva", DepartmentID = 3, Year = GradeLevel.ThirdYear, ID = 130, Scores = [46, 73, 93, 68] },
new() { FirstName = "Cassie", LastName = "Hicks", DepartmentID = 3, Year = GradeLevel.ThirdYear, ID = 131, Scores = [85, 60, 85, 56] },
new() { FirstName = "Ifeanacho", LastName = "Jamuike", DepartmentID = 4, Year = GradeLevel.FourthYear, ID = 132, Scores = [54, 98, 56, 61] },
new() { FirstName = "Carmen", LastName = "Vella", DepartmentID = 6, Year = GradeLevel.FourthYear, ID = 133, Scores = [63, 57, 69, 70] },
new() { FirstName = "Noel", LastName = "Svensson", DepartmentID = 4, Year = GradeLevel.FourthYear, ID = 134, Scores = [85, 60, 80, 73] },
new() { FirstName = "Sanna", LastName = "Hansson", DepartmentID = 5, Year = GradeLevel.FirstYear, ID = 135, Scores = [46, 94, 93, 45] },
new() { FirstName = "Sofiya", LastName = "Seleznyova", DepartmentID = 6, Year = GradeLevel.FirstYear, ID = 136, Scores = [74, 45, 87, 55] },
new() { FirstName = "Amy E.", LastName = "Edwards", DepartmentID = 5, Year = GradeLevel.FirstYear, ID = 137, Scores = [87, 59, 55, 70] },
new() { FirstName = "Nancy", LastName = "Engström", DepartmentID = 3, Year = GradeLevel.FirstYear, ID = 138, Scores = [75, 73, 78, 83] },
new() { FirstName = "Katerina", LastName = "Kovaleva", DepartmentID = 2, Year = GradeLevel.FirstYear, ID = 139, Scores = [44, 50, 47, 41] },
new() { FirstName = "Ifunanya", LastName = "Ugomma", DepartmentID = 4, Year = GradeLevel.FirstYear, ID = 140, Scores = [84, 82, 96, 80] },
new() { FirstName = "Don", LastName = "Richardson", DepartmentID = 5, Year = GradeLevel.FirstYear, ID = 141, Scores = [47, 91, 73, 68] },
new() { FirstName = "Josephine", LastName = "Balzan", DepartmentID = 6, Year = GradeLevel.SecondYear, ID = 142, Scores = [40, 47, 63, 42] },
new() { FirstName = "Michelle", LastName = "Caruana", DepartmentID = -1, Year = GradeLevel.FirstYear, ID = 143, Scores = [97, 92, 69, 77] },
new() { FirstName = "Gaby", LastName = "Frost", DepartmentID = 2, Year = GradeLevel.FirstYear, ID = 144, Scores = [70, 79, 47, 79] },
new() { FirstName = "Erna", LastName = "Nilsson", DepartmentID = 3, Year = GradeLevel.FirstYear, ID = 145, Scores = [56, 52, 51, 51] },
new() { FirstName = "Naima", LastName = "Larsson", DepartmentID = 4, Year = GradeLevel.ThirdYear, ID = 146, Scores = [65, 81, 44, 61] },
new() { FirstName = "Donald", LastName = "Urquhart", DepartmentID = 1, Year = GradeLevel.FirstYear, ID = 147, Scores = [92, 90, 95, 57] },
new() { FirstName = "Nadezhda", LastName = "Kolpakova", DepartmentID = 1, Year = GradeLevel.FirstYear, ID = 148, Scores = [94, 69, 52, 58] },
new() { FirstName = "Ruth", LastName = "Olsson", DepartmentID = 2, Year = GradeLevel.FourthYear, ID = 149, Scores = [66, 49, 82, 74] },
new() { FirstName = "Maria", LastName = "Sammut", DepartmentID = 2, Year = GradeLevel.FirstYear, ID = 150, Scores = [43, 83, 94, 60] },
new() { FirstName = "Veronika", LastName = "Berg", DepartmentID = 3, Year = GradeLevel.FirstYear, ID = 151, Scores = [59, 76, 65, 92] },
new() { FirstName = "Nicholas", LastName = "Micallef", DepartmentID = 3, Year = GradeLevel.FirstYear, ID = 152, Scores = [44, 57, 52, 63] },
new() { FirstName = "Izuchukwu", LastName = "Adaobi", DepartmentID = 4, Year = GradeLevel.SecondYear, ID = 153, Scores = [51, 40, 42, 54] },
new() { FirstName = "Nwanneka", LastName = "Ifeoma", DepartmentID = 4, Year = GradeLevel.FirstYear, ID = 154, Scores = [44, 70, 98, 56] },
new() { FirstName = "John", LastName = "Falzon", DepartmentID = 5, Year = GradeLevel.FirstYear, ID = 155, Scores = [77, 65, 83, 45] },
new() { FirstName = "Martina", LastName = "Mattsson", DepartmentID = 5, Year = GradeLevel.ThirdYear, ID = 156, Scores = [51, 49, 96, 72] },
new() { FirstName = "Jeanette", LastName = "Berggren", DepartmentID = 4, Year = GradeLevel.FirstYear, ID = 157, Scores = [41, 67, 46, 68] },
new() { FirstName = "Anastasiya", LastName = "Sazonova", DepartmentID = 2, Year = GradeLevel.FirstYear, ID = 158, Scores = [53, 96, 76, 49] },
new() { FirstName = "Bruce", LastName = "Keever", DepartmentID = 3, Year = GradeLevel.FirstYear, ID = 159, Scores = [54, 81, 84, 81] },
new() { FirstName = "Sami", LastName = "Åkesson", DepartmentID = 5, Year = GradeLevel.FourthYear, ID = 160, Scores = [45, 85, 79, 94] },
new() { FirstName = "Jesper", LastName = "Jakobsson", DepartmentID = 1, Year = GradeLevel.FirstYear, ID = 161, Scores = [59, 98, 47, 92] },
new() { FirstName = "Max", LastName = "Lindgren", DepartmentID = 2, Year = GradeLevel.FirstYear, ID = 162, Scores = [86, 88, 96, 63] },
new() { FirstName = "Arina", LastName = "Ivanova", DepartmentID = 1, Year = GradeLevel.FirstYear, ID = 163, Scores = [93, 63, 70, 80] }
];
public static IEnumerable<Teacher> Teachers =>
[
new() { First = "Ann", Last = "Beebe", ID = 901, City = "Seattle" },
new() { First = "Alex", Last = "Robinson", ID = 910, City = "Redmond" },
new() { First = "Michiyo", Last = "Sato", ID = 921, City = "Tacoma" },
new() { First = "Aylin", Last = "Lundgren", ID = 932, City = "Seattle" },
new() { First = "Gleb", Last = "Seleznyov", ID = 943, City = "Redmond" },
new() { First = "Alexandra", Last = "Voronova", ID = 954, City = "Tacoma" },
new() { First = "Kevin", Last = "McDowell", ID = 965, City = "Redmond" },
new() { First = "Selma", Last = "Nyberg", ID = 976, City = "Seattle" },
new() { First = "Selma", Last = "Åstrom", ID = 987, City = "Redmond" },
new() { First = "Hillevi", Last = "Bengtsson", ID = 998, City = "Tacoma" },
new() { First = "Allan", Last = "Sandberg", ID = 912, City = "Seattle" },
new() { First = "Dmitry", Last = "Degtyarev", ID = 923, City = "Redmond" },
new() { First = "Arinze", Last = "Madu", ID = 934, City = "Seattle" },
new() { First = "Andrey", Last = "Glazkov", ID = 945, City = "Redmond" },
new() { First = "Kettil", Last = "Berggren", ID = 956, City = "Tacoma" },
new() { First = "Hanying", Last = "Feng", ID = 967, City = "Seattle" },
new() { First = "Hugo", Last = "Garcia", ID = 978, City = "Redmond" },
new() { First = "Michael", Last = "Tucker", ID = 989, City = "Tacoma" },
new() { First = "Ifeanacho", Last = "Jamuike", ID = 991, City = "Redmond" },
new() { First = "Carmen", Last = "Vella", ID = 982, City = "Tacoma" },
new() { First = "Noel", Last = "Svensson", ID = 973, City = "Seattle" }
];
}author: '' ms.author: '' ms.topic: include ms.date: 08/11/2025
Group query results
Grouping is one of the most powerful capabilities of LINQ. The following examples show how to group data in various ways:
- By a single property.
- By the first letter of a string property.
- By a computed numeric range.
- By Boolean predicate or other expression.
- By a compound key.
In addition, the last two queries project their results into a new anonymous type that contains only the student's first and family name. For more information, see the group clause.
Group by single property example
The following example shows how to group source elements by using a single property of the element as the group key. The key is an enum, the student's year in school. The grouping operation uses the default equality comparer for the type.
sample · csharpdocs/csharp/linq/standard-query-operators/snippets/standard-query-operators/GroupQueryResults.csGroupByPropertyQuery
namespace StandardQueryOperators;
public class GroupQueryResults
{
private static readonly IEnumerable<Student> students = Sources.Students;
public static void RunAllSnippets()
{
Console.WriteLine("Group ByProperty Results");
GroupByPropertyQuery();
Console.WriteLine("Group ByProperty Results Method");
GroupByPropertyMethod();
Console.WriteLine("Group ByValue Results");
GroupByValueQuery();
Console.WriteLine("Group ByValue Results Method");
GroupByValueMethod();
Console.WriteLine("Group ByRange Results");
GroupByRangeQuery();
Console.WriteLine("Group ByRange Results Method");
GroupByRangeMethod ();
Console.WriteLine("Group ByBoolean Results");
GroupByBooleanQuery();
Console.WriteLine("Group ByBoolean Results Method");
GroupByBooleanMethod();
Console.WriteLine("Group ByCompoundKey Results");
GroupByCompoundKeyQuery();
Console.WriteLine("Group ByCompoundKey Results Method");
GroupByCompoundKeyMethod();
}
public static void GroupByPropertyQuery()
{
// <GroupByPropertyQuery>
var groupByYearQuery =
from student in students
group student by student.Year into newGroup
orderby newGroup.Key
select newGroup;
foreach (var yearGroup in groupByYearQuery)
{
Console.WriteLine($"Key: {yearGroup.Key}");
foreach (var student in yearGroup)
{
Console.WriteLine($"\t{student.LastName}, {student.FirstName}");
}
}
// </GroupByPropertyQuery>
}
public static void GroupByPropertyMethod()
{
// <GroupByPropertyMethod>
// Variable groupByYearQuery is an IEnumerable<IGrouping<GradeLevel,
// DataClass.Student>>.
var groupByYearQuery = students
.GroupBy(student => student.Year)
.OrderBy(newGroup => newGroup.Key);
foreach (var yearGroup in groupByYearQuery)
{
Console.WriteLine($"Key: {yearGroup.Key}");
foreach (var student in yearGroup)
{
Console.WriteLine($"\t{student.LastName}, {student.FirstName}");
}
}
// </GroupByPropertyMethod>
}
public static void GroupByValueQuery()
{
// <GroupByValueQuery>
var groupByFirstLetterQuery =
from student in students
let firstLetter = student.LastName[0]
group student by firstLetter;
foreach (var studentGroup in groupByFirstLetterQuery)
{
Console.WriteLine($"Key: {studentGroup.Key}");
foreach (var student in studentGroup)
{
Console.WriteLine($"\t{student.LastName}, {student.FirstName}");
}
}
// </GroupByValueQuery>
}
public static void GroupByValueMethod()
{
// <GroupByValueMethod>
var groupByFirstLetterQuery = students
.GroupBy(student => student.LastName[0]);
foreach (var studentGroup in groupByFirstLetterQuery)
{
Console.WriteLine($"Key: {studentGroup.Key}");
foreach (var student in studentGroup)
{
Console.WriteLine($"\t{student.LastName}, {student.FirstName}");
}
}
// </GroupByValueMethod>
}
public static void GroupByRangeQuery()
{
// <GroupByRangeQuery>
static int GetPercentile(Student s)
{
double avg = s.Scores.Average();
return avg > 0 ? (int)avg / 10 : 0;
}
var groupByPercentileQuery =
from student in students
let percentile = GetPercentile(student)
group new
{
student.FirstName,
student.LastName
} by percentile into percentGroup
orderby percentGroup.Key
select percentGroup;
foreach (var studentGroup in groupByPercentileQuery)
{
Console.WriteLine($"Key: {studentGroup.Key * 10}");
foreach (var item in studentGroup)
{
Console.WriteLine($"\t{item.LastName}, {item.FirstName}");
}
}
// </GroupByRangeQuery>
}
public static void GroupByRangeMethod()
{
// <GroupByRangeMethod>
static int GetPercentile(Student s)
{
double avg = s.Scores.Average();
return avg > 0 ? (int)avg / 10 : 0;
}
var groupByPercentileQuery = students
.Select(student => new { student, percentile = GetPercentile(student) })
.GroupBy(student => student.percentile)
.Select(percentGroup => new
{
percentGroup.Key,
Students = percentGroup.Select(s => new { s.student.FirstName, s.student.LastName })
})
.OrderBy(percentGroup => percentGroup.Key);
foreach (var studentGroup in groupByPercentileQuery)
{
Console.WriteLine($"Key: {studentGroup.Key * 10}");
foreach (var item in studentGroup.Students)
{
Console.WriteLine($"\t{item.LastName}, {item.FirstName}");
}
}
// </GroupByRangeMethod>
}
public static void GroupByBooleanQuery()
{
// <GroupByBooleanQuerySyntax>
var groupByHighAverageQuery =
from student in students
group new
{
student.FirstName,
student.LastName
} by student.Scores.Average() > 75 into studentGroup
select studentGroup;
foreach (var studentGroup in groupByHighAverageQuery)
{
Console.WriteLine($"Key: {studentGroup.Key}");
foreach (var student in studentGroup)
{
Console.WriteLine($"\t{student.FirstName} {student.LastName}");
}
}
// </GroupByBooleanQuerySyntax>
}
public static void GroupByBooleanMethod()
{
// <GroupByBooleanMethodSyntax>
var groupByHighAverageQuery = students
.GroupBy(student => student.Scores.Average() > 75)
.Select(group => new
{
group.Key,
Students = group.AsEnumerable().Select(s => new { s.FirstName, s.LastName })
});
foreach (var studentGroup in groupByHighAverageQuery)
{
Console.WriteLine($"Key: {studentGroup.Key}");
foreach (var student in studentGroup.Students)
{
Console.WriteLine($"\t{student.FirstName} {student.LastName}");
}
}
// </GroupByBooleanMethodSyntax>
}
public static void GroupByCompoundKeyQuery()
{
// <GroupByCompundKeyQuerySyntax>
var groupByCompoundKey =
from student in students
group student by new
{
FirstLetterOfLastName = student.LastName[0],
IsScoreOver85 = student.Scores[0] > 85
} into studentGroup
orderby studentGroup.Key.FirstLetterOfLastName
select studentGroup;
foreach (var scoreGroup in groupByCompoundKey)
{
var s = scoreGroup.Key.IsScoreOver85 ? "more than 85" : "less than 85";
Console.WriteLine($"Name starts with {scoreGroup.Key.FirstLetterOfLastName} who scored {s}");
foreach (var item in scoreGroup)
{
Console.WriteLine($"\t{item.FirstName} {item.LastName}");
}
}
// </GroupByCompundKeyQuerySyntax>
}
public static void GroupByCompoundKeyMethod()
{
// <GroupByCompundKeyMethodSyntax>
var groupByCompoundKey = students
.GroupBy(student => new
{
FirstLetterOfLastName = student.LastName[0],
IsScoreOver85 = student.Scores[0] > 85
})
.OrderBy(studentGroup => studentGroup.Key.FirstLetterOfLastName);
foreach (var scoreGroup in groupByCompoundKey)
{
var s = scoreGroup.Key.IsScoreOver85 ? "more than 85" : "less than 85";
Console.WriteLine($"Name starts with {scoreGroup.Key.FirstLetterOfLastName} who scored {s}");
foreach (var item in scoreGroup)
{
Console.WriteLine($"\t{item.FirstName} {item.LastName}");
}
}
// </GroupByCompundKeyMethodSyntax>
}
}The equivalent code using method syntax is shown in the following example:
sample · csharpdocs/csharp/linq/standard-query-operators/snippets/standard-query-operators/GroupQueryResults.csGroupByPropertyMethod
namespace StandardQueryOperators;
public class GroupQueryResults
{
private static readonly IEnumerable<Student> students = Sources.Students;
public static void RunAllSnippets()
{
Console.WriteLine("Group ByProperty Results");
GroupByPropertyQuery();
Console.WriteLine("Group ByProperty Results Method");
GroupByPropertyMethod();
Console.WriteLine("Group ByValue Results");
GroupByValueQuery();
Console.WriteLine("Group ByValue Results Method");
GroupByValueMethod();
Console.WriteLine("Group ByRange Results");
GroupByRangeQuery();
Console.WriteLine("Group ByRange Results Method");
GroupByRangeMethod ();
Console.WriteLine("Group ByBoolean Results");
GroupByBooleanQuery();
Console.WriteLine("Group ByBoolean Results Method");
GroupByBooleanMethod();
Console.WriteLine("Group ByCompoundKey Results");
GroupByCompoundKeyQuery();
Console.WriteLine("Group ByCompoundKey Results Method");
GroupByCompoundKeyMethod();
}
public static void GroupByPropertyQuery()
{
// <GroupByPropertyQuery>
var groupByYearQuery =
from student in students
group student by student.Year into newGroup
orderby newGroup.Key
select newGroup;
foreach (var yearGroup in groupByYearQuery)
{
Console.WriteLine($"Key: {yearGroup.Key}");
foreach (var student in yearGroup)
{
Console.WriteLine($"\t{student.LastName}, {student.FirstName}");
}
}
// </GroupByPropertyQuery>
}
public static void GroupByPropertyMethod()
{
// <GroupByPropertyMethod>
// Variable groupByYearQuery is an IEnumerable<IGrouping<GradeLevel,
// DataClass.Student>>.
var groupByYearQuery = students
.GroupBy(student => student.Year)
.OrderBy(newGroup => newGroup.Key);
foreach (var yearGroup in groupByYearQuery)
{
Console.WriteLine($"Key: {yearGroup.Key}");
foreach (var student in yearGroup)
{
Console.WriteLine($"\t{student.LastName}, {student.FirstName}");
}
}
// </GroupByPropertyMethod>
}
public static void GroupByValueQuery()
{
// <GroupByValueQuery>
var groupByFirstLetterQuery =
from student in students
let firstLetter = student.LastName[0]
group student by firstLetter;
foreach (var studentGroup in groupByFirstLetterQuery)
{
Console.WriteLine($"Key: {studentGroup.Key}");
foreach (var student in studentGroup)
{
Console.WriteLine($"\t{student.LastName}, {student.FirstName}");
}
}
// </GroupByValueQuery>
}
public static void GroupByValueMethod()
{
// <GroupByValueMethod>
var groupByFirstLetterQuery = students
.GroupBy(student => student.LastName[0]);
foreach (var studentGroup in groupByFirstLetterQuery)
{
Console.WriteLine($"Key: {studentGroup.Key}");
foreach (var student in studentGroup)
{
Console.WriteLine($"\t{student.LastName}, {student.FirstName}");
}
}
// </GroupByValueMethod>
}
public static void GroupByRangeQuery()
{
// <GroupByRangeQuery>
static int GetPercentile(Student s)
{
double avg = s.Scores.Average();
return avg > 0 ? (int)avg / 10 : 0;
}
var groupByPercentileQuery =
from student in students
let percentile = GetPercentile(student)
group new
{
student.FirstName,
student.LastName
} by percentile into percentGroup
orderby percentGroup.Key
select percentGroup;
foreach (var studentGroup in groupByPercentileQuery)
{
Console.WriteLine($"Key: {studentGroup.Key * 10}");
foreach (var item in studentGroup)
{
Console.WriteLine($"\t{item.LastName}, {item.FirstName}");
}
}
// </GroupByRangeQuery>
}
public static void GroupByRangeMethod()
{
// <GroupByRangeMethod>
static int GetPercentile(Student s)
{
double avg = s.Scores.Average();
return avg > 0 ? (int)avg / 10 : 0;
}
var groupByPercentileQuery = students
.Select(student => new { student, percentile = GetPercentile(student) })
.GroupBy(student => student.percentile)
.Select(percentGroup => new
{
percentGroup.Key,
Students = percentGroup.Select(s => new { s.student.FirstName, s.student.LastName })
})
.OrderBy(percentGroup => percentGroup.Key);
foreach (var studentGroup in groupByPercentileQuery)
{
Console.WriteLine($"Key: {studentGroup.Key * 10}");
foreach (var item in studentGroup.Students)
{
Console.WriteLine($"\t{item.LastName}, {item.FirstName}");
}
}
// </GroupByRangeMethod>
}
public static void GroupByBooleanQuery()
{
// <GroupByBooleanQuerySyntax>
var groupByHighAverageQuery =
from student in students
group new
{
student.FirstName,
student.LastName
} by student.Scores.Average() > 75 into studentGroup
select studentGroup;
foreach (var studentGroup in groupByHighAverageQuery)
{
Console.WriteLine($"Key: {studentGroup.Key}");
foreach (var student in studentGroup)
{
Console.WriteLine($"\t{student.FirstName} {student.LastName}");
}
}
// </GroupByBooleanQuerySyntax>
}
public static void GroupByBooleanMethod()
{
// <GroupByBooleanMethodSyntax>
var groupByHighAverageQuery = students
.GroupBy(student => student.Scores.Average() > 75)
.Select(group => new
{
group.Key,
Students = group.AsEnumerable().Select(s => new { s.FirstName, s.LastName })
});
foreach (var studentGroup in groupByHighAverageQuery)
{
Console.WriteLine($"Key: {studentGroup.Key}");
foreach (var student in studentGroup.Students)
{
Console.WriteLine($"\t{student.FirstName} {student.LastName}");
}
}
// </GroupByBooleanMethodSyntax>
}
public static void GroupByCompoundKeyQuery()
{
// <GroupByCompundKeyQuerySyntax>
var groupByCompoundKey =
from student in students
group student by new
{
FirstLetterOfLastName = student.LastName[0],
IsScoreOver85 = student.Scores[0] > 85
} into studentGroup
orderby studentGroup.Key.FirstLetterOfLastName
select studentGroup;
foreach (var scoreGroup in groupByCompoundKey)
{
var s = scoreGroup.Key.IsScoreOver85 ? "more than 85" : "less than 85";
Console.WriteLine($"Name starts with {scoreGroup.Key.FirstLetterOfLastName} who scored {s}");
foreach (var item in scoreGroup)
{
Console.WriteLine($"\t{item.FirstName} {item.LastName}");
}
}
// </GroupByCompundKeyQuerySyntax>
}
public static void GroupByCompoundKeyMethod()
{
// <GroupByCompundKeyMethodSyntax>
var groupByCompoundKey = students
.GroupBy(student => new
{
FirstLetterOfLastName = student.LastName[0],
IsScoreOver85 = student.Scores[0] > 85
})
.OrderBy(studentGroup => studentGroup.Key.FirstLetterOfLastName);
foreach (var scoreGroup in groupByCompoundKey)
{
var s = scoreGroup.Key.IsScoreOver85 ? "more than 85" : "less than 85";
Console.WriteLine($"Name starts with {scoreGroup.Key.FirstLetterOfLastName} who scored {s}");
foreach (var item in scoreGroup)
{
Console.WriteLine($"\t{item.FirstName} {item.LastName}");
}
}
// </GroupByCompundKeyMethodSyntax>
}
}Group by value example
The following example shows how to group source elements by using something other than a property of the object for the group key. In this example, the key is the first letter of the student's family name.
sample · csharpdocs/csharp/linq/standard-query-operators/snippets/standard-query-operators/GroupQueryResults.csGroupByValueQuery
namespace StandardQueryOperators;
public class GroupQueryResults
{
private static readonly IEnumerable<Student> students = Sources.Students;
public static void RunAllSnippets()
{
Console.WriteLine("Group ByProperty Results");
GroupByPropertyQuery();
Console.WriteLine("Group ByProperty Results Method");
GroupByPropertyMethod();
Console.WriteLine("Group ByValue Results");
GroupByValueQuery();
Console.WriteLine("Group ByValue Results Method");
GroupByValueMethod();
Console.WriteLine("Group ByRange Results");
GroupByRangeQuery();
Console.WriteLine("Group ByRange Results Method");
GroupByRangeMethod ();
Console.WriteLine("Group ByBoolean Results");
GroupByBooleanQuery();
Console.WriteLine("Group ByBoolean Results Method");
GroupByBooleanMethod();
Console.WriteLine("Group ByCompoundKey Results");
GroupByCompoundKeyQuery();
Console.WriteLine("Group ByCompoundKey Results Method");
GroupByCompoundKeyMethod();
}
public static void GroupByPropertyQuery()
{
// <GroupByPropertyQuery>
var groupByYearQuery =
from student in students
group student by student.Year into newGroup
orderby newGroup.Key
select newGroup;
foreach (var yearGroup in groupByYearQuery)
{
Console.WriteLine($"Key: {yearGroup.Key}");
foreach (var student in yearGroup)
{
Console.WriteLine($"\t{student.LastName}, {student.FirstName}");
}
}
// </GroupByPropertyQuery>
}
public static void GroupByPropertyMethod()
{
// <GroupByPropertyMethod>
// Variable groupByYearQuery is an IEnumerable<IGrouping<GradeLevel,
// DataClass.Student>>.
var groupByYearQuery = students
.GroupBy(student => student.Year)
.OrderBy(newGroup => newGroup.Key);
foreach (var yearGroup in groupByYearQuery)
{
Console.WriteLine($"Key: {yearGroup.Key}");
foreach (var student in yearGroup)
{
Console.WriteLine($"\t{student.LastName}, {student.FirstName}");
}
}
// </GroupByPropertyMethod>
}
public static void GroupByValueQuery()
{
// <GroupByValueQuery>
var groupByFirstLetterQuery =
from student in students
let firstLetter = student.LastName[0]
group student by firstLetter;
foreach (var studentGroup in groupByFirstLetterQuery)
{
Console.WriteLine($"Key: {studentGroup.Key}");
foreach (var student in studentGroup)
{
Console.WriteLine($"\t{student.LastName}, {student.FirstName}");
}
}
// </GroupByValueQuery>
}
public static void GroupByValueMethod()
{
// <GroupByValueMethod>
var groupByFirstLetterQuery = students
.GroupBy(student => student.LastName[0]);
foreach (var studentGroup in groupByFirstLetterQuery)
{
Console.WriteLine($"Key: {studentGroup.Key}");
foreach (var student in studentGroup)
{
Console.WriteLine($"\t{student.LastName}, {student.FirstName}");
}
}
// </GroupByValueMethod>
}
public static void GroupByRangeQuery()
{
// <GroupByRangeQuery>
static int GetPercentile(Student s)
{
double avg = s.Scores.Average();
return avg > 0 ? (int)avg / 10 : 0;
}
var groupByPercentileQuery =
from student in students
let percentile = GetPercentile(student)
group new
{
student.FirstName,
student.LastName
} by percentile into percentGroup
orderby percentGroup.Key
select percentGroup;
foreach (var studentGroup in groupByPercentileQuery)
{
Console.WriteLine($"Key: {studentGroup.Key * 10}");
foreach (var item in studentGroup)
{
Console.WriteLine($"\t{item.LastName}, {item.FirstName}");
}
}
// </GroupByRangeQuery>
}
public static void GroupByRangeMethod()
{
// <GroupByRangeMethod>
static int GetPercentile(Student s)
{
double avg = s.Scores.Average();
return avg > 0 ? (int)avg / 10 : 0;
}
var groupByPercentileQuery = students
.Select(student => new { student, percentile = GetPercentile(student) })
.GroupBy(student => student.percentile)
.Select(percentGroup => new
{
percentGroup.Key,
Students = percentGroup.Select(s => new { s.student.FirstName, s.student.LastName })
})
.OrderBy(percentGroup => percentGroup.Key);
foreach (var studentGroup in groupByPercentileQuery)
{
Console.WriteLine($"Key: {studentGroup.Key * 10}");
foreach (var item in studentGroup.Students)
{
Console.WriteLine($"\t{item.LastName}, {item.FirstName}");
}
}
// </GroupByRangeMethod>
}
public static void GroupByBooleanQuery()
{
// <GroupByBooleanQuerySyntax>
var groupByHighAverageQuery =
from student in students
group new
{
student.FirstName,
student.LastName
} by student.Scores.Average() > 75 into studentGroup
select studentGroup;
foreach (var studentGroup in groupByHighAverageQuery)
{
Console.WriteLine($"Key: {studentGroup.Key}");
foreach (var student in studentGroup)
{
Console.WriteLine($"\t{student.FirstName} {student.LastName}");
}
}
// </GroupByBooleanQuerySyntax>
}
public static void GroupByBooleanMethod()
{
// <GroupByBooleanMethodSyntax>
var groupByHighAverageQuery = students
.GroupBy(student => student.Scores.Average() > 75)
.Select(group => new
{
group.Key,
Students = group.AsEnumerable().Select(s => new { s.FirstName, s.LastName })
});
foreach (var studentGroup in groupByHighAverageQuery)
{
Console.WriteLine($"Key: {studentGroup.Key}");
foreach (var student in studentGroup.Students)
{
Console.WriteLine($"\t{student.FirstName} {student.LastName}");
}
}
// </GroupByBooleanMethodSyntax>
}
public static void GroupByCompoundKeyQuery()
{
// <GroupByCompundKeyQuerySyntax>
var groupByCompoundKey =
from student in students
group student by new
{
FirstLetterOfLastName = student.LastName[0],
IsScoreOver85 = student.Scores[0] > 85
} into studentGroup
orderby studentGroup.Key.FirstLetterOfLastName
select studentGroup;
foreach (var scoreGroup in groupByCompoundKey)
{
var s = scoreGroup.Key.IsScoreOver85 ? "more than 85" : "less than 85";
Console.WriteLine($"Name starts with {scoreGroup.Key.FirstLetterOfLastName} who scored {s}");
foreach (var item in scoreGroup)
{
Console.WriteLine($"\t{item.FirstName} {item.LastName}");
}
}
// </GroupByCompundKeyQuerySyntax>
}
public static void GroupByCompoundKeyMethod()
{
// <GroupByCompundKeyMethodSyntax>
var groupByCompoundKey = students
.GroupBy(student => new
{
FirstLetterOfLastName = student.LastName[0],
IsScoreOver85 = student.Scores[0] > 85
})
.OrderBy(studentGroup => studentGroup.Key.FirstLetterOfLastName);
foreach (var scoreGroup in groupByCompoundKey)
{
var s = scoreGroup.Key.IsScoreOver85 ? "more than 85" : "less than 85";
Console.WriteLine($"Name starts with {scoreGroup.Key.FirstLetterOfLastName} who scored {s}");
foreach (var item in scoreGroup)
{
Console.WriteLine($"\t{item.FirstName} {item.LastName}");
}
}
// </GroupByCompundKeyMethodSyntax>
}
}Nested foreach is required to access group items.
The equivalent code using method syntax is shown in the following example:
sample · csharpdocs/csharp/linq/standard-query-operators/snippets/standard-query-operators/GroupQueryResults.csGroupByValueMethod
namespace StandardQueryOperators;
public class GroupQueryResults
{
private static readonly IEnumerable<Student> students = Sources.Students;
public static void RunAllSnippets()
{
Console.WriteLine("Group ByProperty Results");
GroupByPropertyQuery();
Console.WriteLine("Group ByProperty Results Method");
GroupByPropertyMethod();
Console.WriteLine("Group ByValue Results");
GroupByValueQuery();
Console.WriteLine("Group ByValue Results Method");
GroupByValueMethod();
Console.WriteLine("Group ByRange Results");
GroupByRangeQuery();
Console.WriteLine("Group ByRange Results Method");
GroupByRangeMethod ();
Console.WriteLine("Group ByBoolean Results");
GroupByBooleanQuery();
Console.WriteLine("Group ByBoolean Results Method");
GroupByBooleanMethod();
Console.WriteLine("Group ByCompoundKey Results");
GroupByCompoundKeyQuery();
Console.WriteLine("Group ByCompoundKey Results Method");
GroupByCompoundKeyMethod();
}
public static void GroupByPropertyQuery()
{
// <GroupByPropertyQuery>
var groupByYearQuery =
from student in students
group student by student.Year into newGroup
orderby newGroup.Key
select newGroup;
foreach (var yearGroup in groupByYearQuery)
{
Console.WriteLine($"Key: {yearGroup.Key}");
foreach (var student in yearGroup)
{
Console.WriteLine($"\t{student.LastName}, {student.FirstName}");
}
}
// </GroupByPropertyQuery>
}
public static void GroupByPropertyMethod()
{
// <GroupByPropertyMethod>
// Variable groupByYearQuery is an IEnumerable<IGrouping<GradeLevel,
// DataClass.Student>>.
var groupByYearQuery = students
.GroupBy(student => student.Year)
.OrderBy(newGroup => newGroup.Key);
foreach (var yearGroup in groupByYearQuery)
{
Console.WriteLine($"Key: {yearGroup.Key}");
foreach (var student in yearGroup)
{
Console.WriteLine($"\t{student.LastName}, {student.FirstName}");
}
}
// </GroupByPropertyMethod>
}
public static void GroupByValueQuery()
{
// <GroupByValueQuery>
var groupByFirstLetterQuery =
from student in students
let firstLetter = student.LastName[0]
group student by firstLetter;
foreach (var studentGroup in groupByFirstLetterQuery)
{
Console.WriteLine($"Key: {studentGroup.Key}");
foreach (var student in studentGroup)
{
Console.WriteLine($"\t{student.LastName}, {student.FirstName}");
}
}
// </GroupByValueQuery>
}
public static void GroupByValueMethod()
{
// <GroupByValueMethod>
var groupByFirstLetterQuery = students
.GroupBy(student => student.LastName[0]);
foreach (var studentGroup in groupByFirstLetterQuery)
{
Console.WriteLine($"Key: {studentGroup.Key}");
foreach (var student in studentGroup)
{
Console.WriteLine($"\t{student.LastName}, {student.FirstName}");
}
}
// </GroupByValueMethod>
}
public static void GroupByRangeQuery()
{
// <GroupByRangeQuery>
static int GetPercentile(Student s)
{
double avg = s.Scores.Average();
return avg > 0 ? (int)avg / 10 : 0;
}
var groupByPercentileQuery =
from student in students
let percentile = GetPercentile(student)
group new
{
student.FirstName,
student.LastName
} by percentile into percentGroup
orderby percentGroup.Key
select percentGroup;
foreach (var studentGroup in groupByPercentileQuery)
{
Console.WriteLine($"Key: {studentGroup.Key * 10}");
foreach (var item in studentGroup)
{
Console.WriteLine($"\t{item.LastName}, {item.FirstName}");
}
}
// </GroupByRangeQuery>
}
public static void GroupByRangeMethod()
{
// <GroupByRangeMethod>
static int GetPercentile(Student s)
{
double avg = s.Scores.Average();
return avg > 0 ? (int)avg / 10 : 0;
}
var groupByPercentileQuery = students
.Select(student => new { student, percentile = GetPercentile(student) })
.GroupBy(student => student.percentile)
.Select(percentGroup => new
{
percentGroup.Key,
Students = percentGroup.Select(s => new { s.student.FirstName, s.student.LastName })
})
.OrderBy(percentGroup => percentGroup.Key);
foreach (var studentGroup in groupByPercentileQuery)
{
Console.WriteLine($"Key: {studentGroup.Key * 10}");
foreach (var item in studentGroup.Students)
{
Console.WriteLine($"\t{item.LastName}, {item.FirstName}");
}
}
// </GroupByRangeMethod>
}
public static void GroupByBooleanQuery()
{
// <GroupByBooleanQuerySyntax>
var groupByHighAverageQuery =
from student in students
group new
{
student.FirstName,
student.LastName
} by student.Scores.Average() > 75 into studentGroup
select studentGroup;
foreach (var studentGroup in groupByHighAverageQuery)
{
Console.WriteLine($"Key: {studentGroup.Key}");
foreach (var student in studentGroup)
{
Console.WriteLine($"\t{student.FirstName} {student.LastName}");
}
}
// </GroupByBooleanQuerySyntax>
}
public static void GroupByBooleanMethod()
{
// <GroupByBooleanMethodSyntax>
var groupByHighAverageQuery = students
.GroupBy(student => student.Scores.Average() > 75)
.Select(group => new
{
group.Key,
Students = group.AsEnumerable().Select(s => new { s.FirstName, s.LastName })
});
foreach (var studentGroup in groupByHighAverageQuery)
{
Console.WriteLine($"Key: {studentGroup.Key}");
foreach (var student in studentGroup.Students)
{
Console.WriteLine($"\t{student.FirstName} {student.LastName}");
}
}
// </GroupByBooleanMethodSyntax>
}
public static void GroupByCompoundKeyQuery()
{
// <GroupByCompundKeyQuerySyntax>
var groupByCompoundKey =
from student in students
group student by new
{
FirstLetterOfLastName = student.LastName[0],
IsScoreOver85 = student.Scores[0] > 85
} into studentGroup
orderby studentGroup.Key.FirstLetterOfLastName
select studentGroup;
foreach (var scoreGroup in groupByCompoundKey)
{
var s = scoreGroup.Key.IsScoreOver85 ? "more than 85" : "less than 85";
Console.WriteLine($"Name starts with {scoreGroup.Key.FirstLetterOfLastName} who scored {s}");
foreach (var item in scoreGroup)
{
Console.WriteLine($"\t{item.FirstName} {item.LastName}");
}
}
// </GroupByCompundKeyQuerySyntax>
}
public static void GroupByCompoundKeyMethod()
{
// <GroupByCompundKeyMethodSyntax>
var groupByCompoundKey = students
.GroupBy(student => new
{
FirstLetterOfLastName = student.LastName[0],
IsScoreOver85 = student.Scores[0] > 85
})
.OrderBy(studentGroup => studentGroup.Key.FirstLetterOfLastName);
foreach (var scoreGroup in groupByCompoundKey)
{
var s = scoreGroup.Key.IsScoreOver85 ? "more than 85" : "less than 85";
Console.WriteLine($"Name starts with {scoreGroup.Key.FirstLetterOfLastName} who scored {s}");
foreach (var item in scoreGroup)
{
Console.WriteLine($"\t{item.FirstName} {item.LastName}");
}
}
// </GroupByCompundKeyMethodSyntax>
}
}Group by a range example
The following example shows how to group source elements by using a numeric range as a group key. The query then projects the results into an anonymous type that contains only the first and family name and the percentile range to which the student belongs. An anonymous type is used because it isn't necessary to use the complete Student object to display the results. GetPercentile is a helper function that calculates a percentile based on the student's average score. The method returns an integer between 0 and 10.
sample · csharpdocs/csharp/linq/standard-query-operators/snippets/standard-query-operators/GroupQueryResults.csGroupByRangeQuery
namespace StandardQueryOperators;
public class GroupQueryResults
{
private static readonly IEnumerable<Student> students = Sources.Students;
public static void RunAllSnippets()
{
Console.WriteLine("Group ByProperty Results");
GroupByPropertyQuery();
Console.WriteLine("Group ByProperty Results Method");
GroupByPropertyMethod();
Console.WriteLine("Group ByValue Results");
GroupByValueQuery();
Console.WriteLine("Group ByValue Results Method");
GroupByValueMethod();
Console.WriteLine("Group ByRange Results");
GroupByRangeQuery();
Console.WriteLine("Group ByRange Results Method");
GroupByRangeMethod ();
Console.WriteLine("Group ByBoolean Results");
GroupByBooleanQuery();
Console.WriteLine("Group ByBoolean Results Method");
GroupByBooleanMethod();
Console.WriteLine("Group ByCompoundKey Results");
GroupByCompoundKeyQuery();
Console.WriteLine("Group ByCompoundKey Results Method");
GroupByCompoundKeyMethod();
}
public static void GroupByPropertyQuery()
{
// <GroupByPropertyQuery>
var groupByYearQuery =
from student in students
group student by student.Year into newGroup
orderby newGroup.Key
select newGroup;
foreach (var yearGroup in groupByYearQuery)
{
Console.WriteLine($"Key: {yearGroup.Key}");
foreach (var student in yearGroup)
{
Console.WriteLine($"\t{student.LastName}, {student.FirstName}");
}
}
// </GroupByPropertyQuery>
}
public static void GroupByPropertyMethod()
{
// <GroupByPropertyMethod>
// Variable groupByYearQuery is an IEnumerable<IGrouping<GradeLevel,
// DataClass.Student>>.
var groupByYearQuery = students
.GroupBy(student => student.Year)
.OrderBy(newGroup => newGroup.Key);
foreach (var yearGroup in groupByYearQuery)
{
Console.WriteLine($"Key: {yearGroup.Key}");
foreach (var student in yearGroup)
{
Console.WriteLine($"\t{student.LastName}, {student.FirstName}");
}
}
// </GroupByPropertyMethod>
}
public static void GroupByValueQuery()
{
// <GroupByValueQuery>
var groupByFirstLetterQuery =
from student in students
let firstLetter = student.LastName[0]
group student by firstLetter;
foreach (var studentGroup in groupByFirstLetterQuery)
{
Console.WriteLine($"Key: {studentGroup.Key}");
foreach (var student in studentGroup)
{
Console.WriteLine($"\t{student.LastName}, {student.FirstName}");
}
}
// </GroupByValueQuery>
}
public static void GroupByValueMethod()
{
// <GroupByValueMethod>
var groupByFirstLetterQuery = students
.GroupBy(student => student.LastName[0]);
foreach (var studentGroup in groupByFirstLetterQuery)
{
Console.WriteLine($"Key: {studentGroup.Key}");
foreach (var student in studentGroup)
{
Console.WriteLine($"\t{student.LastName}, {student.FirstName}");
}
}
// </GroupByValueMethod>
}
public static void GroupByRangeQuery()
{
// <GroupByRangeQuery>
static int GetPercentile(Student s)
{
double avg = s.Scores.Average();
return avg > 0 ? (int)avg / 10 : 0;
}
var groupByPercentileQuery =
from student in students
let percentile = GetPercentile(student)
group new
{
student.FirstName,
student.LastName
} by percentile into percentGroup
orderby percentGroup.Key
select percentGroup;
foreach (var studentGroup in groupByPercentileQuery)
{
Console.WriteLine($"Key: {studentGroup.Key * 10}");
foreach (var item in studentGroup)
{
Console.WriteLine($"\t{item.LastName}, {item.FirstName}");
}
}
// </GroupByRangeQuery>
}
public static void GroupByRangeMethod()
{
// <GroupByRangeMethod>
static int GetPercentile(Student s)
{
double avg = s.Scores.Average();
return avg > 0 ? (int)avg / 10 : 0;
}
var groupByPercentileQuery = students
.Select(student => new { student, percentile = GetPercentile(student) })
.GroupBy(student => student.percentile)
.Select(percentGroup => new
{
percentGroup.Key,
Students = percentGroup.Select(s => new { s.student.FirstName, s.student.LastName })
})
.OrderBy(percentGroup => percentGroup.Key);
foreach (var studentGroup in groupByPercentileQuery)
{
Console.WriteLine($"Key: {studentGroup.Key * 10}");
foreach (var item in studentGroup.Students)
{
Console.WriteLine($"\t{item.LastName}, {item.FirstName}");
}
}
// </GroupByRangeMethod>
}
public static void GroupByBooleanQuery()
{
// <GroupByBooleanQuerySyntax>
var groupByHighAverageQuery =
from student in students
group new
{
student.FirstName,
student.LastName
} by student.Scores.Average() > 75 into studentGroup
select studentGroup;
foreach (var studentGroup in groupByHighAverageQuery)
{
Console.WriteLine($"Key: {studentGroup.Key}");
foreach (var student in studentGroup)
{
Console.WriteLine($"\t{student.FirstName} {student.LastName}");
}
}
// </GroupByBooleanQuerySyntax>
}
public static void GroupByBooleanMethod()
{
// <GroupByBooleanMethodSyntax>
var groupByHighAverageQuery = students
.GroupBy(student => student.Scores.Average() > 75)
.Select(group => new
{
group.Key,
Students = group.AsEnumerable().Select(s => new { s.FirstName, s.LastName })
});
foreach (var studentGroup in groupByHighAverageQuery)
{
Console.WriteLine($"Key: {studentGroup.Key}");
foreach (var student in studentGroup.Students)
{
Console.WriteLine($"\t{student.FirstName} {student.LastName}");
}
}
// </GroupByBooleanMethodSyntax>
}
public static void GroupByCompoundKeyQuery()
{
// <GroupByCompundKeyQuerySyntax>
var groupByCompoundKey =
from student in students
group student by new
{
FirstLetterOfLastName = student.LastName[0],
IsScoreOver85 = student.Scores[0] > 85
} into studentGroup
orderby studentGroup.Key.FirstLetterOfLastName
select studentGroup;
foreach (var scoreGroup in groupByCompoundKey)
{
var s = scoreGroup.Key.IsScoreOver85 ? "more than 85" : "less than 85";
Console.WriteLine($"Name starts with {scoreGroup.Key.FirstLetterOfLastName} who scored {s}");
foreach (var item in scoreGroup)
{
Console.WriteLine($"\t{item.FirstName} {item.LastName}");
}
}
// </GroupByCompundKeyQuerySyntax>
}
public static void GroupByCompoundKeyMethod()
{
// <GroupByCompundKeyMethodSyntax>
var groupByCompoundKey = students
.GroupBy(student => new
{
FirstLetterOfLastName = student.LastName[0],
IsScoreOver85 = student.Scores[0] > 85
})
.OrderBy(studentGroup => studentGroup.Key.FirstLetterOfLastName);
foreach (var scoreGroup in groupByCompoundKey)
{
var s = scoreGroup.Key.IsScoreOver85 ? "more than 85" : "less than 85";
Console.WriteLine($"Name starts with {scoreGroup.Key.FirstLetterOfLastName} who scored {s}");
foreach (var item in scoreGroup)
{
Console.WriteLine($"\t{item.FirstName} {item.LastName}");
}
}
// </GroupByCompundKeyMethodSyntax>
}
}Nested foreach required to iterate over groups and group items. The equivalent code using method syntax is shown in the following example:
sample · csharpdocs/csharp/linq/standard-query-operators/snippets/standard-query-operators/GroupQueryResults.csGroupByRangeMethod
namespace StandardQueryOperators;
public class GroupQueryResults
{
private static readonly IEnumerable<Student> students = Sources.Students;
public static void RunAllSnippets()
{
Console.WriteLine("Group ByProperty Results");
GroupByPropertyQuery();
Console.WriteLine("Group ByProperty Results Method");
GroupByPropertyMethod();
Console.WriteLine("Group ByValue Results");
GroupByValueQuery();
Console.WriteLine("Group ByValue Results Method");
GroupByValueMethod();
Console.WriteLine("Group ByRange Results");
GroupByRangeQuery();
Console.WriteLine("Group ByRange Results Method");
GroupByRangeMethod ();
Console.WriteLine("Group ByBoolean Results");
GroupByBooleanQuery();
Console.WriteLine("Group ByBoolean Results Method");
GroupByBooleanMethod();
Console.WriteLine("Group ByCompoundKey Results");
GroupByCompoundKeyQuery();
Console.WriteLine("Group ByCompoundKey Results Method");
GroupByCompoundKeyMethod();
}
public static void GroupByPropertyQuery()
{
// <GroupByPropertyQuery>
var groupByYearQuery =
from student in students
group student by student.Year into newGroup
orderby newGroup.Key
select newGroup;
foreach (var yearGroup in groupByYearQuery)
{
Console.WriteLine($"Key: {yearGroup.Key}");
foreach (var student in yearGroup)
{
Console.WriteLine($"\t{student.LastName}, {student.FirstName}");
}
}
// </GroupByPropertyQuery>
}
public static void GroupByPropertyMethod()
{
// <GroupByPropertyMethod>
// Variable groupByYearQuery is an IEnumerable<IGrouping<GradeLevel,
// DataClass.Student>>.
var groupByYearQuery = students
.GroupBy(student => student.Year)
.OrderBy(newGroup => newGroup.Key);
foreach (var yearGroup in groupByYearQuery)
{
Console.WriteLine($"Key: {yearGroup.Key}");
foreach (var student in yearGroup)
{
Console.WriteLine($"\t{student.LastName}, {student.FirstName}");
}
}
// </GroupByPropertyMethod>
}
public static void GroupByValueQuery()
{
// <GroupByValueQuery>
var groupByFirstLetterQuery =
from student in students
let firstLetter = student.LastName[0]
group student by firstLetter;
foreach (var studentGroup in groupByFirstLetterQuery)
{
Console.WriteLine($"Key: {studentGroup.Key}");
foreach (var student in studentGroup)
{
Console.WriteLine($"\t{student.LastName}, {student.FirstName}");
}
}
// </GroupByValueQuery>
}
public static void GroupByValueMethod()
{
// <GroupByValueMethod>
var groupByFirstLetterQuery = students
.GroupBy(student => student.LastName[0]);
foreach (var studentGroup in groupByFirstLetterQuery)
{
Console.WriteLine($"Key: {studentGroup.Key}");
foreach (var student in studentGroup)
{
Console.WriteLine($"\t{student.LastName}, {student.FirstName}");
}
}
// </GroupByValueMethod>
}
public static void GroupByRangeQuery()
{
// <GroupByRangeQuery>
static int GetPercentile(Student s)
{
double avg = s.Scores.Average();
return avg > 0 ? (int)avg / 10 : 0;
}
var groupByPercentileQuery =
from student in students
let percentile = GetPercentile(student)
group new
{
student.FirstName,
student.LastName
} by percentile into percentGroup
orderby percentGroup.Key
select percentGroup;
foreach (var studentGroup in groupByPercentileQuery)
{
Console.WriteLine($"Key: {studentGroup.Key * 10}");
foreach (var item in studentGroup)
{
Console.WriteLine($"\t{item.LastName}, {item.FirstName}");
}
}
// </GroupByRangeQuery>
}
public static void GroupByRangeMethod()
{
// <GroupByRangeMethod>
static int GetPercentile(Student s)
{
double avg = s.Scores.Average();
return avg > 0 ? (int)avg / 10 : 0;
}
var groupByPercentileQuery = students
.Select(student => new { student, percentile = GetPercentile(student) })
.GroupBy(student => student.percentile)
.Select(percentGroup => new
{
percentGroup.Key,
Students = percentGroup.Select(s => new { s.student.FirstName, s.student.LastName })
})
.OrderBy(percentGroup => percentGroup.Key);
foreach (var studentGroup in groupByPercentileQuery)
{
Console.WriteLine($"Key: {studentGroup.Key * 10}");
foreach (var item in studentGroup.Students)
{
Console.WriteLine($"\t{item.LastName}, {item.FirstName}");
}
}
// </GroupByRangeMethod>
}
public static void GroupByBooleanQuery()
{
// <GroupByBooleanQuerySyntax>
var groupByHighAverageQuery =
from student in students
group new
{
student.FirstName,
student.LastName
} by student.Scores.Average() > 75 into studentGroup
select studentGroup;
foreach (var studentGroup in groupByHighAverageQuery)
{
Console.WriteLine($"Key: {studentGroup.Key}");
foreach (var student in studentGroup)
{
Console.WriteLine($"\t{student.FirstName} {student.LastName}");
}
}
// </GroupByBooleanQuerySyntax>
}
public static void GroupByBooleanMethod()
{
// <GroupByBooleanMethodSyntax>
var groupByHighAverageQuery = students
.GroupBy(student => student.Scores.Average() > 75)
.Select(group => new
{
group.Key,
Students = group.AsEnumerable().Select(s => new { s.FirstName, s.LastName })
});
foreach (var studentGroup in groupByHighAverageQuery)
{
Console.WriteLine($"Key: {studentGroup.Key}");
foreach (var student in studentGroup.Students)
{
Console.WriteLine($"\t{student.FirstName} {student.LastName}");
}
}
// </GroupByBooleanMethodSyntax>
}
public static void GroupByCompoundKeyQuery()
{
// <GroupByCompundKeyQuerySyntax>
var groupByCompoundKey =
from student in students
group student by new
{
FirstLetterOfLastName = student.LastName[0],
IsScoreOver85 = student.Scores[0] > 85
} into studentGroup
orderby studentGroup.Key.FirstLetterOfLastName
select studentGroup;
foreach (var scoreGroup in groupByCompoundKey)
{
var s = scoreGroup.Key.IsScoreOver85 ? "more than 85" : "less than 85";
Console.WriteLine($"Name starts with {scoreGroup.Key.FirstLetterOfLastName} who scored {s}");
foreach (var item in scoreGroup)
{
Console.WriteLine($"\t{item.FirstName} {item.LastName}");
}
}
// </GroupByCompundKeyQuerySyntax>
}
public static void GroupByCompoundKeyMethod()
{
// <GroupByCompundKeyMethodSyntax>
var groupByCompoundKey = students
.GroupBy(student => new
{
FirstLetterOfLastName = student.LastName[0],
IsScoreOver85 = student.Scores[0] > 85
})
.OrderBy(studentGroup => studentGroup.Key.FirstLetterOfLastName);
foreach (var scoreGroup in groupByCompoundKey)
{
var s = scoreGroup.Key.IsScoreOver85 ? "more than 85" : "less than 85";
Console.WriteLine($"Name starts with {scoreGroup.Key.FirstLetterOfLastName} who scored {s}");
foreach (var item in scoreGroup)
{
Console.WriteLine($"\t{item.FirstName} {item.LastName}");
}
}
// </GroupByCompundKeyMethodSyntax>
}
}Group by comparison example
The following example shows how to group source elements by using a Boolean comparison expression. In this example, the Boolean expression tests whether a student's average exam score is greater than 75. As in previous examples, the results are projected into an anonymous type because the complete source element isn't needed. The properties in the anonymous type become properties on the Key member.
sample · csharpdocs/csharp/linq/standard-query-operators/snippets/standard-query-operators/GroupQueryResults.csGroupByBooleanQuerySyntax
namespace StandardQueryOperators;
public class GroupQueryResults
{
private static readonly IEnumerable<Student> students = Sources.Students;
public static void RunAllSnippets()
{
Console.WriteLine("Group ByProperty Results");
GroupByPropertyQuery();
Console.WriteLine("Group ByProperty Results Method");
GroupByPropertyMethod();
Console.WriteLine("Group ByValue Results");
GroupByValueQuery();
Console.WriteLine("Group ByValue Results Method");
GroupByValueMethod();
Console.WriteLine("Group ByRange Results");
GroupByRangeQuery();
Console.WriteLine("Group ByRange Results Method");
GroupByRangeMethod ();
Console.WriteLine("Group ByBoolean Results");
GroupByBooleanQuery();
Console.WriteLine("Group ByBoolean Results Method");
GroupByBooleanMethod();
Console.WriteLine("Group ByCompoundKey Results");
GroupByCompoundKeyQuery();
Console.WriteLine("Group ByCompoundKey Results Method");
GroupByCompoundKeyMethod();
}
public static void GroupByPropertyQuery()
{
// <GroupByPropertyQuery>
var groupByYearQuery =
from student in students
group student by student.Year into newGroup
orderby newGroup.Key
select newGroup;
foreach (var yearGroup in groupByYearQuery)
{
Console.WriteLine($"Key: {yearGroup.Key}");
foreach (var student in yearGroup)
{
Console.WriteLine($"\t{student.LastName}, {student.FirstName}");
}
}
// </GroupByPropertyQuery>
}
public static void GroupByPropertyMethod()
{
// <GroupByPropertyMethod>
// Variable groupByYearQuery is an IEnumerable<IGrouping<GradeLevel,
// DataClass.Student>>.
var groupByYearQuery = students
.GroupBy(student => student.Year)
.OrderBy(newGroup => newGroup.Key);
foreach (var yearGroup in groupByYearQuery)
{
Console.WriteLine($"Key: {yearGroup.Key}");
foreach (var student in yearGroup)
{
Console.WriteLine($"\t{student.LastName}, {student.FirstName}");
}
}
// </GroupByPropertyMethod>
}
public static void GroupByValueQuery()
{
// <GroupByValueQuery>
var groupByFirstLetterQuery =
from student in students
let firstLetter = student.LastName[0]
group student by firstLetter;
foreach (var studentGroup in groupByFirstLetterQuery)
{
Console.WriteLine($"Key: {studentGroup.Key}");
foreach (var student in studentGroup)
{
Console.WriteLine($"\t{student.LastName}, {student.FirstName}");
}
}
// </GroupByValueQuery>
}
public static void GroupByValueMethod()
{
// <GroupByValueMethod>
var groupByFirstLetterQuery = students
.GroupBy(student => student.LastName[0]);
foreach (var studentGroup in groupByFirstLetterQuery)
{
Console.WriteLine($"Key: {studentGroup.Key}");
foreach (var student in studentGroup)
{
Console.WriteLine($"\t{student.LastName}, {student.FirstName}");
}
}
// </GroupByValueMethod>
}
public static void GroupByRangeQuery()
{
// <GroupByRangeQuery>
static int GetPercentile(Student s)
{
double avg = s.Scores.Average();
return avg > 0 ? (int)avg / 10 : 0;
}
var groupByPercentileQuery =
from student in students
let percentile = GetPercentile(student)
group new
{
student.FirstName,
student.LastName
} by percentile into percentGroup
orderby percentGroup.Key
select percentGroup;
foreach (var studentGroup in groupByPercentileQuery)
{
Console.WriteLine($"Key: {studentGroup.Key * 10}");
foreach (var item in studentGroup)
{
Console.WriteLine($"\t{item.LastName}, {item.FirstName}");
}
}
// </GroupByRangeQuery>
}
public static void GroupByRangeMethod()
{
// <GroupByRangeMethod>
static int GetPercentile(Student s)
{
double avg = s.Scores.Average();
return avg > 0 ? (int)avg / 10 : 0;
}
var groupByPercentileQuery = students
.Select(student => new { student, percentile = GetPercentile(student) })
.GroupBy(student => student.percentile)
.Select(percentGroup => new
{
percentGroup.Key,
Students = percentGroup.Select(s => new { s.student.FirstName, s.student.LastName })
})
.OrderBy(percentGroup => percentGroup.Key);
foreach (var studentGroup in groupByPercentileQuery)
{
Console.WriteLine($"Key: {studentGroup.Key * 10}");
foreach (var item in studentGroup.Students)
{
Console.WriteLine($"\t{item.LastName}, {item.FirstName}");
}
}
// </GroupByRangeMethod>
}
public static void GroupByBooleanQuery()
{
// <GroupByBooleanQuerySyntax>
var groupByHighAverageQuery =
from student in students
group new
{
student.FirstName,
student.LastName
} by student.Scores.Average() > 75 into studentGroup
select studentGroup;
foreach (var studentGroup in groupByHighAverageQuery)
{
Console.WriteLine($"Key: {studentGroup.Key}");
foreach (var student in studentGroup)
{
Console.WriteLine($"\t{student.FirstName} {student.LastName}");
}
}
// </GroupByBooleanQuerySyntax>
}
public static void GroupByBooleanMethod()
{
// <GroupByBooleanMethodSyntax>
var groupByHighAverageQuery = students
.GroupBy(student => student.Scores.Average() > 75)
.Select(group => new
{
group.Key,
Students = group.AsEnumerable().Select(s => new { s.FirstName, s.LastName })
});
foreach (var studentGroup in groupByHighAverageQuery)
{
Console.WriteLine($"Key: {studentGroup.Key}");
foreach (var student in studentGroup.Students)
{
Console.WriteLine($"\t{student.FirstName} {student.LastName}");
}
}
// </GroupByBooleanMethodSyntax>
}
public static void GroupByCompoundKeyQuery()
{
// <GroupByCompundKeyQuerySyntax>
var groupByCompoundKey =
from student in students
group student by new
{
FirstLetterOfLastName = student.LastName[0],
IsScoreOver85 = student.Scores[0] > 85
} into studentGroup
orderby studentGroup.Key.FirstLetterOfLastName
select studentGroup;
foreach (var scoreGroup in groupByCompoundKey)
{
var s = scoreGroup.Key.IsScoreOver85 ? "more than 85" : "less than 85";
Console.WriteLine($"Name starts with {scoreGroup.Key.FirstLetterOfLastName} who scored {s}");
foreach (var item in scoreGroup)
{
Console.WriteLine($"\t{item.FirstName} {item.LastName}");
}
}
// </GroupByCompundKeyQuerySyntax>
}
public static void GroupByCompoundKeyMethod()
{
// <GroupByCompundKeyMethodSyntax>
var groupByCompoundKey = students
.GroupBy(student => new
{
FirstLetterOfLastName = student.LastName[0],
IsScoreOver85 = student.Scores[0] > 85
})
.OrderBy(studentGroup => studentGroup.Key.FirstLetterOfLastName);
foreach (var scoreGroup in groupByCompoundKey)
{
var s = scoreGroup.Key.IsScoreOver85 ? "more than 85" : "less than 85";
Console.WriteLine($"Name starts with {scoreGroup.Key.FirstLetterOfLastName} who scored {s}");
foreach (var item in scoreGroup)
{
Console.WriteLine($"\t{item.FirstName} {item.LastName}");
}
}
// </GroupByCompundKeyMethodSyntax>
}
}The equivalent query using method syntax is shown in the following code:
sample · csharpdocs/csharp/linq/standard-query-operators/snippets/standard-query-operators/GroupQueryResults.csGroupByBooleanMethodSyntax
namespace StandardQueryOperators;
public class GroupQueryResults
{
private static readonly IEnumerable<Student> students = Sources.Students;
public static void RunAllSnippets()
{
Console.WriteLine("Group ByProperty Results");
GroupByPropertyQuery();
Console.WriteLine("Group ByProperty Results Method");
GroupByPropertyMethod();
Console.WriteLine("Group ByValue Results");
GroupByValueQuery();
Console.WriteLine("Group ByValue Results Method");
GroupByValueMethod();
Console.WriteLine("Group ByRange Results");
GroupByRangeQuery();
Console.WriteLine("Group ByRange Results Method");
GroupByRangeMethod ();
Console.WriteLine("Group ByBoolean Results");
GroupByBooleanQuery();
Console.WriteLine("Group ByBoolean Results Method");
GroupByBooleanMethod();
Console.WriteLine("Group ByCompoundKey Results");
GroupByCompoundKeyQuery();
Console.WriteLine("Group ByCompoundKey Results Method");
GroupByCompoundKeyMethod();
}
public static void GroupByPropertyQuery()
{
// <GroupByPropertyQuery>
var groupByYearQuery =
from student in students
group student by student.Year into newGroup
orderby newGroup.Key
select newGroup;
foreach (var yearGroup in groupByYearQuery)
{
Console.WriteLine($"Key: {yearGroup.Key}");
foreach (var student in yearGroup)
{
Console.WriteLine($"\t{student.LastName}, {student.FirstName}");
}
}
// </GroupByPropertyQuery>
}
public static void GroupByPropertyMethod()
{
// <GroupByPropertyMethod>
// Variable groupByYearQuery is an IEnumerable<IGrouping<GradeLevel,
// DataClass.Student>>.
var groupByYearQuery = students
.GroupBy(student => student.Year)
.OrderBy(newGroup => newGroup.Key);
foreach (var yearGroup in groupByYearQuery)
{
Console.WriteLine($"Key: {yearGroup.Key}");
foreach (var student in yearGroup)
{
Console.WriteLine($"\t{student.LastName}, {student.FirstName}");
}
}
// </GroupByPropertyMethod>
}
public static void GroupByValueQuery()
{
// <GroupByValueQuery>
var groupByFirstLetterQuery =
from student in students
let firstLetter = student.LastName[0]
group student by firstLetter;
foreach (var studentGroup in groupByFirstLetterQuery)
{
Console.WriteLine($"Key: {studentGroup.Key}");
foreach (var student in studentGroup)
{
Console.WriteLine($"\t{student.LastName}, {student.FirstName}");
}
}
// </GroupByValueQuery>
}
public static void GroupByValueMethod()
{
// <GroupByValueMethod>
var groupByFirstLetterQuery = students
.GroupBy(student => student.LastName[0]);
foreach (var studentGroup in groupByFirstLetterQuery)
{
Console.WriteLine($"Key: {studentGroup.Key}");
foreach (var student in studentGroup)
{
Console.WriteLine($"\t{student.LastName}, {student.FirstName}");
}
}
// </GroupByValueMethod>
}
public static void GroupByRangeQuery()
{
// <GroupByRangeQuery>
static int GetPercentile(Student s)
{
double avg = s.Scores.Average();
return avg > 0 ? (int)avg / 10 : 0;
}
var groupByPercentileQuery =
from student in students
let percentile = GetPercentile(student)
group new
{
student.FirstName,
student.LastName
} by percentile into percentGroup
orderby percentGroup.Key
select percentGroup;
foreach (var studentGroup in groupByPercentileQuery)
{
Console.WriteLine($"Key: {studentGroup.Key * 10}");
foreach (var item in studentGroup)
{
Console.WriteLine($"\t{item.LastName}, {item.FirstName}");
}
}
// </GroupByRangeQuery>
}
public static void GroupByRangeMethod()
{
// <GroupByRangeMethod>
static int GetPercentile(Student s)
{
double avg = s.Scores.Average();
return avg > 0 ? (int)avg / 10 : 0;
}
var groupByPercentileQuery = students
.Select(student => new { student, percentile = GetPercentile(student) })
.GroupBy(student => student.percentile)
.Select(percentGroup => new
{
percentGroup.Key,
Students = percentGroup.Select(s => new { s.student.FirstName, s.student.LastName })
})
.OrderBy(percentGroup => percentGroup.Key);
foreach (var studentGroup in groupByPercentileQuery)
{
Console.WriteLine($"Key: {studentGroup.Key * 10}");
foreach (var item in studentGroup.Students)
{
Console.WriteLine($"\t{item.LastName}, {item.FirstName}");
}
}
// </GroupByRangeMethod>
}
public static void GroupByBooleanQuery()
{
// <GroupByBooleanQuerySyntax>
var groupByHighAverageQuery =
from student in students
group new
{
student.FirstName,
student.LastName
} by student.Scores.Average() > 75 into studentGroup
select studentGroup;
foreach (var studentGroup in groupByHighAverageQuery)
{
Console.WriteLine($"Key: {studentGroup.Key}");
foreach (var student in studentGroup)
{
Console.WriteLine($"\t{student.FirstName} {student.LastName}");
}
}
// </GroupByBooleanQuerySyntax>
}
public static void GroupByBooleanMethod()
{
// <GroupByBooleanMethodSyntax>
var groupByHighAverageQuery = students
.GroupBy(student => student.Scores.Average() > 75)
.Select(group => new
{
group.Key,
Students = group.AsEnumerable().Select(s => new { s.FirstName, s.LastName })
});
foreach (var studentGroup in groupByHighAverageQuery)
{
Console.WriteLine($"Key: {studentGroup.Key}");
foreach (var student in studentGroup.Students)
{
Console.WriteLine($"\t{student.FirstName} {student.LastName}");
}
}
// </GroupByBooleanMethodSyntax>
}
public static void GroupByCompoundKeyQuery()
{
// <GroupByCompundKeyQuerySyntax>
var groupByCompoundKey =
from student in students
group student by new
{
FirstLetterOfLastName = student.LastName[0],
IsScoreOver85 = student.Scores[0] > 85
} into studentGroup
orderby studentGroup.Key.FirstLetterOfLastName
select studentGroup;
foreach (var scoreGroup in groupByCompoundKey)
{
var s = scoreGroup.Key.IsScoreOver85 ? "more than 85" : "less than 85";
Console.WriteLine($"Name starts with {scoreGroup.Key.FirstLetterOfLastName} who scored {s}");
foreach (var item in scoreGroup)
{
Console.WriteLine($"\t{item.FirstName} {item.LastName}");
}
}
// </GroupByCompundKeyQuerySyntax>
}
public static void GroupByCompoundKeyMethod()
{
// <GroupByCompundKeyMethodSyntax>
var groupByCompoundKey = students
.GroupBy(student => new
{
FirstLetterOfLastName = student.LastName[0],
IsScoreOver85 = student.Scores[0] > 85
})
.OrderBy(studentGroup => studentGroup.Key.FirstLetterOfLastName);
foreach (var scoreGroup in groupByCompoundKey)
{
var s = scoreGroup.Key.IsScoreOver85 ? "more than 85" : "less than 85";
Console.WriteLine($"Name starts with {scoreGroup.Key.FirstLetterOfLastName} who scored {s}");
foreach (var item in scoreGroup)
{
Console.WriteLine($"\t{item.FirstName} {item.LastName}");
}
}
// </GroupByCompundKeyMethodSyntax>
}
}Group by anonymous type
The following example shows how to use an anonymous type to encapsulate a key that contains multiple values. In this example, the first key value is the first letter of the student's family name. The second key value is a Boolean that specifies whether the student scored over 85 on the first exam. You can order the groups by any property in the key.
sample · csharpdocs/csharp/linq/standard-query-operators/snippets/standard-query-operators/GroupQueryResults.csGroupByCompundKeyQuerySyntax
namespace StandardQueryOperators;
public class GroupQueryResults
{
private static readonly IEnumerable<Student> students = Sources.Students;
public static void RunAllSnippets()
{
Console.WriteLine("Group ByProperty Results");
GroupByPropertyQuery();
Console.WriteLine("Group ByProperty Results Method");
GroupByPropertyMethod();
Console.WriteLine("Group ByValue Results");
GroupByValueQuery();
Console.WriteLine("Group ByValue Results Method");
GroupByValueMethod();
Console.WriteLine("Group ByRange Results");
GroupByRangeQuery();
Console.WriteLine("Group ByRange Results Method");
GroupByRangeMethod ();
Console.WriteLine("Group ByBoolean Results");
GroupByBooleanQuery();
Console.WriteLine("Group ByBoolean Results Method");
GroupByBooleanMethod();
Console.WriteLine("Group ByCompoundKey Results");
GroupByCompoundKeyQuery();
Console.WriteLine("Group ByCompoundKey Results Method");
GroupByCompoundKeyMethod();
}
public static void GroupByPropertyQuery()
{
// <GroupByPropertyQuery>
var groupByYearQuery =
from student in students
group student by student.Year into newGroup
orderby newGroup.Key
select newGroup;
foreach (var yearGroup in groupByYearQuery)
{
Console.WriteLine($"Key: {yearGroup.Key}");
foreach (var student in yearGroup)
{
Console.WriteLine($"\t{student.LastName}, {student.FirstName}");
}
}
// </GroupByPropertyQuery>
}
public static void GroupByPropertyMethod()
{
// <GroupByPropertyMethod>
// Variable groupByYearQuery is an IEnumerable<IGrouping<GradeLevel,
// DataClass.Student>>.
var groupByYearQuery = students
.GroupBy(student => student.Year)
.OrderBy(newGroup => newGroup.Key);
foreach (var yearGroup in groupByYearQuery)
{
Console.WriteLine($"Key: {yearGroup.Key}");
foreach (var student in yearGroup)
{
Console.WriteLine($"\t{student.LastName}, {student.FirstName}");
}
}
// </GroupByPropertyMethod>
}
public static void GroupByValueQuery()
{
// <GroupByValueQuery>
var groupByFirstLetterQuery =
from student in students
let firstLetter = student.LastName[0]
group student by firstLetter;
foreach (var studentGroup in groupByFirstLetterQuery)
{
Console.WriteLine($"Key: {studentGroup.Key}");
foreach (var student in studentGroup)
{
Console.WriteLine($"\t{student.LastName}, {student.FirstName}");
}
}
// </GroupByValueQuery>
}
public static void GroupByValueMethod()
{
// <GroupByValueMethod>
var groupByFirstLetterQuery = students
.GroupBy(student => student.LastName[0]);
foreach (var studentGroup in groupByFirstLetterQuery)
{
Console.WriteLine($"Key: {studentGroup.Key}");
foreach (var student in studentGroup)
{
Console.WriteLine($"\t{student.LastName}, {student.FirstName}");
}
}
// </GroupByValueMethod>
}
public static void GroupByRangeQuery()
{
// <GroupByRangeQuery>
static int GetPercentile(Student s)
{
double avg = s.Scores.Average();
return avg > 0 ? (int)avg / 10 : 0;
}
var groupByPercentileQuery =
from student in students
let percentile = GetPercentile(student)
group new
{
student.FirstName,
student.LastName
} by percentile into percentGroup
orderby percentGroup.Key
select percentGroup;
foreach (var studentGroup in groupByPercentileQuery)
{
Console.WriteLine($"Key: {studentGroup.Key * 10}");
foreach (var item in studentGroup)
{
Console.WriteLine($"\t{item.LastName}, {item.FirstName}");
}
}
// </GroupByRangeQuery>
}
public static void GroupByRangeMethod()
{
// <GroupByRangeMethod>
static int GetPercentile(Student s)
{
double avg = s.Scores.Average();
return avg > 0 ? (int)avg / 10 : 0;
}
var groupByPercentileQuery = students
.Select(student => new { student, percentile = GetPercentile(student) })
.GroupBy(student => student.percentile)
.Select(percentGroup => new
{
percentGroup.Key,
Students = percentGroup.Select(s => new { s.student.FirstName, s.student.LastName })
})
.OrderBy(percentGroup => percentGroup.Key);
foreach (var studentGroup in groupByPercentileQuery)
{
Console.WriteLine($"Key: {studentGroup.Key * 10}");
foreach (var item in studentGroup.Students)
{
Console.WriteLine($"\t{item.LastName}, {item.FirstName}");
}
}
// </GroupByRangeMethod>
}
public static void GroupByBooleanQuery()
{
// <GroupByBooleanQuerySyntax>
var groupByHighAverageQuery =
from student in students
group new
{
student.FirstName,
student.LastName
} by student.Scores.Average() > 75 into studentGroup
select studentGroup;
foreach (var studentGroup in groupByHighAverageQuery)
{
Console.WriteLine($"Key: {studentGroup.Key}");
foreach (var student in studentGroup)
{
Console.WriteLine($"\t{student.FirstName} {student.LastName}");
}
}
// </GroupByBooleanQuerySyntax>
}
public static void GroupByBooleanMethod()
{
// <GroupByBooleanMethodSyntax>
var groupByHighAverageQuery = students
.GroupBy(student => student.Scores.Average() > 75)
.Select(group => new
{
group.Key,
Students = group.AsEnumerable().Select(s => new { s.FirstName, s.LastName })
});
foreach (var studentGroup in groupByHighAverageQuery)
{
Console.WriteLine($"Key: {studentGroup.Key}");
foreach (var student in studentGroup.Students)
{
Console.WriteLine($"\t{student.FirstName} {student.LastName}");
}
}
// </GroupByBooleanMethodSyntax>
}
public static void GroupByCompoundKeyQuery()
{
// <GroupByCompundKeyQuerySyntax>
var groupByCompoundKey =
from student in students
group student by new
{
FirstLetterOfLastName = student.LastName[0],
IsScoreOver85 = student.Scores[0] > 85
} into studentGroup
orderby studentGroup.Key.FirstLetterOfLastName
select studentGroup;
foreach (var scoreGroup in groupByCompoundKey)
{
var s = scoreGroup.Key.IsScoreOver85 ? "more than 85" : "less than 85";
Console.WriteLine($"Name starts with {scoreGroup.Key.FirstLetterOfLastName} who scored {s}");
foreach (var item in scoreGroup)
{
Console.WriteLine($"\t{item.FirstName} {item.LastName}");
}
}
// </GroupByCompundKeyQuerySyntax>
}
public static void GroupByCompoundKeyMethod()
{
// <GroupByCompundKeyMethodSyntax>
var groupByCompoundKey = students
.GroupBy(student => new
{
FirstLetterOfLastName = student.LastName[0],
IsScoreOver85 = student.Scores[0] > 85
})
.OrderBy(studentGroup => studentGroup.Key.FirstLetterOfLastName);
foreach (var scoreGroup in groupByCompoundKey)
{
var s = scoreGroup.Key.IsScoreOver85 ? "more than 85" : "less than 85";
Console.WriteLine($"Name starts with {scoreGroup.Key.FirstLetterOfLastName} who scored {s}");
foreach (var item in scoreGroup)
{
Console.WriteLine($"\t{item.FirstName} {item.LastName}");
}
}
// </GroupByCompundKeyMethodSyntax>
}
}The equivalent query using method syntax is shown in the following code:
sample · csharpdocs/csharp/linq/standard-query-operators/snippets/standard-query-operators/GroupQueryResults.csGroupByCompundKeyMethodSyntax
namespace StandardQueryOperators;
public class GroupQueryResults
{
private static readonly IEnumerable<Student> students = Sources.Students;
public static void RunAllSnippets()
{
Console.WriteLine("Group ByProperty Results");
GroupByPropertyQuery();
Console.WriteLine("Group ByProperty Results Method");
GroupByPropertyMethod();
Console.WriteLine("Group ByValue Results");
GroupByValueQuery();
Console.WriteLine("Group ByValue Results Method");
GroupByValueMethod();
Console.WriteLine("Group ByRange Results");
GroupByRangeQuery();
Console.WriteLine("Group ByRange Results Method");
GroupByRangeMethod ();
Console.WriteLine("Group ByBoolean Results");
GroupByBooleanQuery();
Console.WriteLine("Group ByBoolean Results Method");
GroupByBooleanMethod();
Console.WriteLine("Group ByCompoundKey Results");
GroupByCompoundKeyQuery();
Console.WriteLine("Group ByCompoundKey Results Method");
GroupByCompoundKeyMethod();
}
public static void GroupByPropertyQuery()
{
// <GroupByPropertyQuery>
var groupByYearQuery =
from student in students
group student by student.Year into newGroup
orderby newGroup.Key
select newGroup;
foreach (var yearGroup in groupByYearQuery)
{
Console.WriteLine($"Key: {yearGroup.Key}");
foreach (var student in yearGroup)
{
Console.WriteLine($"\t{student.LastName}, {student.FirstName}");
}
}
// </GroupByPropertyQuery>
}
public static void GroupByPropertyMethod()
{
// <GroupByPropertyMethod>
// Variable groupByYearQuery is an IEnumerable<IGrouping<GradeLevel,
// DataClass.Student>>.
var groupByYearQuery = students
.GroupBy(student => student.Year)
.OrderBy(newGroup => newGroup.Key);
foreach (var yearGroup in groupByYearQuery)
{
Console.WriteLine($"Key: {yearGroup.Key}");
foreach (var student in yearGroup)
{
Console.WriteLine($"\t{student.LastName}, {student.FirstName}");
}
}
// </GroupByPropertyMethod>
}
public static void GroupByValueQuery()
{
// <GroupByValueQuery>
var groupByFirstLetterQuery =
from student in students
let firstLetter = student.LastName[0]
group student by firstLetter;
foreach (var studentGroup in groupByFirstLetterQuery)
{
Console.WriteLine($"Key: {studentGroup.Key}");
foreach (var student in studentGroup)
{
Console.WriteLine($"\t{student.LastName}, {student.FirstName}");
}
}
// </GroupByValueQuery>
}
public static void GroupByValueMethod()
{
// <GroupByValueMethod>
var groupByFirstLetterQuery = students
.GroupBy(student => student.LastName[0]);
foreach (var studentGroup in groupByFirstLetterQuery)
{
Console.WriteLine($"Key: {studentGroup.Key}");
foreach (var student in studentGroup)
{
Console.WriteLine($"\t{student.LastName}, {student.FirstName}");
}
}
// </GroupByValueMethod>
}
public static void GroupByRangeQuery()
{
// <GroupByRangeQuery>
static int GetPercentile(Student s)
{
double avg = s.Scores.Average();
return avg > 0 ? (int)avg / 10 : 0;
}
var groupByPercentileQuery =
from student in students
let percentile = GetPercentile(student)
group new
{
student.FirstName,
student.LastName
} by percentile into percentGroup
orderby percentGroup.Key
select percentGroup;
foreach (var studentGroup in groupByPercentileQuery)
{
Console.WriteLine($"Key: {studentGroup.Key * 10}");
foreach (var item in studentGroup)
{
Console.WriteLine($"\t{item.LastName}, {item.FirstName}");
}
}
// </GroupByRangeQuery>
}
public static void GroupByRangeMethod()
{
// <GroupByRangeMethod>
static int GetPercentile(Student s)
{
double avg = s.Scores.Average();
return avg > 0 ? (int)avg / 10 : 0;
}
var groupByPercentileQuery = students
.Select(student => new { student, percentile = GetPercentile(student) })
.GroupBy(student => student.percentile)
.Select(percentGroup => new
{
percentGroup.Key,
Students = percentGroup.Select(s => new { s.student.FirstName, s.student.LastName })
})
.OrderBy(percentGroup => percentGroup.Key);
foreach (var studentGroup in groupByPercentileQuery)
{
Console.WriteLine($"Key: {studentGroup.Key * 10}");
foreach (var item in studentGroup.Students)
{
Console.WriteLine($"\t{item.LastName}, {item.FirstName}");
}
}
// </GroupByRangeMethod>
}
public static void GroupByBooleanQuery()
{
// <GroupByBooleanQuerySyntax>
var groupByHighAverageQuery =
from student in students
group new
{
student.FirstName,
student.LastName
} by student.Scores.Average() > 75 into studentGroup
select studentGroup;
foreach (var studentGroup in groupByHighAverageQuery)
{
Console.WriteLine($"Key: {studentGroup.Key}");
foreach (var student in studentGroup)
{
Console.WriteLine($"\t{student.FirstName} {student.LastName}");
}
}
// </GroupByBooleanQuerySyntax>
}
public static void GroupByBooleanMethod()
{
// <GroupByBooleanMethodSyntax>
var groupByHighAverageQuery = students
.GroupBy(student => student.Scores.Average() > 75)
.Select(group => new
{
group.Key,
Students = group.AsEnumerable().Select(s => new { s.FirstName, s.LastName })
});
foreach (var studentGroup in groupByHighAverageQuery)
{
Console.WriteLine($"Key: {studentGroup.Key}");
foreach (var student in studentGroup.Students)
{
Console.WriteLine($"\t{student.FirstName} {student.LastName}");
}
}
// </GroupByBooleanMethodSyntax>
}
public static void GroupByCompoundKeyQuery()
{
// <GroupByCompundKeyQuerySyntax>
var groupByCompoundKey =
from student in students
group student by new
{
FirstLetterOfLastName = student.LastName[0],
IsScoreOver85 = student.Scores[0] > 85
} into studentGroup
orderby studentGroup.Key.FirstLetterOfLastName
select studentGroup;
foreach (var scoreGroup in groupByCompoundKey)
{
var s = scoreGroup.Key.IsScoreOver85 ? "more than 85" : "less than 85";
Console.WriteLine($"Name starts with {scoreGroup.Key.FirstLetterOfLastName} who scored {s}");
foreach (var item in scoreGroup)
{
Console.WriteLine($"\t{item.FirstName} {item.LastName}");
}
}
// </GroupByCompundKeyQuerySyntax>
}
public static void GroupByCompoundKeyMethod()
{
// <GroupByCompundKeyMethodSyntax>
var groupByCompoundKey = students
.GroupBy(student => new
{
FirstLetterOfLastName = student.LastName[0],
IsScoreOver85 = student.Scores[0] > 85
})
.OrderBy(studentGroup => studentGroup.Key.FirstLetterOfLastName);
foreach (var scoreGroup in groupByCompoundKey)
{
var s = scoreGroup.Key.IsScoreOver85 ? "more than 85" : "less than 85";
Console.WriteLine($"Name starts with {scoreGroup.Key.FirstLetterOfLastName} who scored {s}");
foreach (var item in scoreGroup)
{
Console.WriteLine($"\t{item.FirstName} {item.LastName}");
}
}
// </GroupByCompundKeyMethodSyntax>
}
}Create a nested group
The following example shows how to create nested groups in a LINQ query expression. Each group that is created according to student year or grade level is then further subdivided into groups based on the individuals' names.
sample · csharpdocs/csharp/linq/standard-query-operators/snippets/standard-query-operators/NestedGroups.csNestedGroupsQuerySyntax
namespace StandardQueryOperators;
public static class NestedGroups
{
private static readonly IEnumerable<Student> students = Sources.Students;
public static void RunAllSnippets()
{
Console.WriteLine("Nested Group Query Syntax");
NestedGroupQuery();
Console.WriteLine("Nested Group Method Syntax");
NestedGroupMethod();
}
private static void NestedGroupQuery()
{
// <NestedGroupsQuerySyntax>
var nestedGroupsQuery =
from student in students
group student by student.Year into newGroup1
from newGroup2 in
from student in newGroup1
group student by student.LastName
group newGroup2 by newGroup1.Key;
foreach (var outerGroup in nestedGroupsQuery)
{
Console.WriteLine($"DataClass.Student Level = {outerGroup.Key}");
foreach (var innerGroup in outerGroup)
{
Console.WriteLine($"\tNames that begin with: {innerGroup.Key}");
foreach (var innerGroupElement in innerGroup)
{
Console.WriteLine($"\t\t{innerGroupElement.LastName} {innerGroupElement.FirstName}");
}
}
}
// </NestedGroupsQuerySyntax>
}
private static void NestedGroupMethod()
{
// <NestedGroupsMethodSyntax>
var nestedGroupsQuery =
students
.GroupBy(student => student.Year)
.Select(newGroup1 => new
{
newGroup1.Key,
NestedGroup = newGroup1
.GroupBy(student => student.LastName)
});
foreach (var outerGroup in nestedGroupsQuery)
{
Console.WriteLine($"DataClass.Student Level = {outerGroup.Key}");
foreach (var innerGroup in outerGroup.NestedGroup)
{
Console.WriteLine($"\tNames that begin with: {innerGroup.Key}");
foreach (var innerGroupElement in innerGroup)
{
Console.WriteLine($"\t\t{innerGroupElement.LastName} {innerGroupElement.FirstName}");
}
}
}
// </NestedGroupsMethodSyntax>
}
}Three nested foreach loops are required to iterate over the inner elements of a nested group.
(Hover the mouse cursor over the iteration variables, outerGroup, innerGroup, and innerGroupElement to see their actual type.)
The equivalent query using method syntax is shown in the following code:
sample · csharpdocs/csharp/linq/standard-query-operators/snippets/standard-query-operators/NestedGroups.csNestedGroupsMethodSyntax
namespace StandardQueryOperators;
public static class NestedGroups
{
private static readonly IEnumerable<Student> students = Sources.Students;
public static void RunAllSnippets()
{
Console.WriteLine("Nested Group Query Syntax");
NestedGroupQuery();
Console.WriteLine("Nested Group Method Syntax");
NestedGroupMethod();
}
private static void NestedGroupQuery()
{
// <NestedGroupsQuerySyntax>
var nestedGroupsQuery =
from student in students
group student by student.Year into newGroup1
from newGroup2 in
from student in newGroup1
group student by student.LastName
group newGroup2 by newGroup1.Key;
foreach (var outerGroup in nestedGroupsQuery)
{
Console.WriteLine($"DataClass.Student Level = {outerGroup.Key}");
foreach (var innerGroup in outerGroup)
{
Console.WriteLine($"\tNames that begin with: {innerGroup.Key}");
foreach (var innerGroupElement in innerGroup)
{
Console.WriteLine($"\t\t{innerGroupElement.LastName} {innerGroupElement.FirstName}");
}
}
}
// </NestedGroupsQuerySyntax>
}
private static void NestedGroupMethod()
{
// <NestedGroupsMethodSyntax>
var nestedGroupsQuery =
students
.GroupBy(student => student.Year)
.Select(newGroup1 => new
{
newGroup1.Key,
NestedGroup = newGroup1
.GroupBy(student => student.LastName)
});
foreach (var outerGroup in nestedGroupsQuery)
{
Console.WriteLine($"DataClass.Student Level = {outerGroup.Key}");
foreach (var innerGroup in outerGroup.NestedGroup)
{
Console.WriteLine($"\tNames that begin with: {innerGroup.Key}");
foreach (var innerGroupElement in innerGroup)
{
Console.WriteLine($"\t\t{innerGroupElement.LastName} {innerGroupElement.FirstName}");
}
}
}
// </NestedGroupsMethodSyntax>
}
}Perform a subquery on a grouping operation
This article shows two different ways to create a query that orders the source data into groups, and then performs a subquery over each group individually. The basic technique in each example is to group the source elements by using a continuation named newGroup, and then generating a new subquery against newGroup. This subquery is run against each new group created by the outer query. In this particular example the final output isn't a group, but a flat sequence of anonymous types.
For more information about how to group, see group clause. For more information about continuations, see into. The following example uses an in-memory data structure as the data source, but the same principles apply for any kind of LINQ data source.
sample · csharpdocs/csharp/linq/standard-query-operators/snippets/standard-query-operators/SubqueryOnGroup.csSubQueryOnGroupQuerySyntax
namespace StandardQueryOperators;
public class SubqueryOnGroup
{
private static readonly IEnumerable<Student> students = Sources.Students;
public static void RunAllSnippets()
{
Console.WriteLine("Subquery on Group");
SubqueryOnGroupQuery();
Console.WriteLine("Subquery on Group Method");
SubqueryOnGroupMethod();
}
private static void SubqueryOnGroupQuery()
{
// <SubQueryOnGroupQuerySyntax>
var queryGroupMax =
from student in students
group student by student.Year into studentGroup
select new
{
Level = studentGroup.Key,
HighestScore = (
from student2 in studentGroup
select student2.Scores.Average()
).Max()
};
var count = queryGroupMax.Count();
Console.WriteLine($"Number of groups = {count}");
foreach (var item in queryGroupMax)
{
Console.WriteLine($" {item.Level} Highest Score={item.HighestScore}");
}
// </SubQueryOnGroupQuerySyntax>
}
public static void SubqueryOnGroupMethod()
{
// <SubQueryOnGroupMethodSyntax>
var queryGroupMax =
students
.GroupBy(student => student.Year)
.Select(studentGroup => new
{
Level = studentGroup.Key,
HighestScore = studentGroup.Max(student2 => student2.Scores.Average())
});
var count = queryGroupMax.Count();
Console.WriteLine($"Number of groups = {count}");
foreach (var item in queryGroupMax)
{
Console.WriteLine($" {item.Level} Highest Score={item.HighestScore}");
}
// </SubQueryOnGroupMethodSyntax>
}
}The query in the preceding snippet can also be written using method syntax. The following code snippet has a semantically equivalent query written using method syntax.
sample · csharpdocs/csharp/linq/standard-query-operators/snippets/standard-query-operators/SubqueryOnGroup.csSubQueryOnGroupMethodSyntax
namespace StandardQueryOperators;
public class SubqueryOnGroup
{
private static readonly IEnumerable<Student> students = Sources.Students;
public static void RunAllSnippets()
{
Console.WriteLine("Subquery on Group");
SubqueryOnGroupQuery();
Console.WriteLine("Subquery on Group Method");
SubqueryOnGroupMethod();
}
private static void SubqueryOnGroupQuery()
{
// <SubQueryOnGroupQuerySyntax>
var queryGroupMax =
from student in students
group student by student.Year into studentGroup
select new
{
Level = studentGroup.Key,
HighestScore = (
from student2 in studentGroup
select student2.Scores.Average()
).Max()
};
var count = queryGroupMax.Count();
Console.WriteLine($"Number of groups = {count}");
foreach (var item in queryGroupMax)
{
Console.WriteLine($" {item.Level} Highest Score={item.HighestScore}");
}
// </SubQueryOnGroupQuerySyntax>
}
public static void SubqueryOnGroupMethod()
{
// <SubQueryOnGroupMethodSyntax>
var queryGroupMax =
students
.GroupBy(student => student.Year)
.Select(studentGroup => new
{
Level = studentGroup.Key,
HighestScore = studentGroup.Max(student2 => student2.Scores.Average())
});
var count = queryGroupMax.Count();
Console.WriteLine($"Number of groups = {count}");
foreach (var item in queryGroupMax)
{
Console.WriteLine($" {item.Level} Highest Score={item.HighestScore}");
}
// </SubQueryOnGroupMethodSyntax>
}
}