Linq order by, group by and order by each group?

Rita picture Rita · Feb 16, 2011 · Viewed 134.6k times · Source

I have an object that looks something like this:

public class Student
{
    public string Name { get; set; } 
    public int Grade { get; set; }
}

I would like to create the following query: group grades by student name, order each student group by grades, and order groups by max grade in each group.

So it will look like this:

A 100
A 80
B 80
B 50
B 40
C 70
C 30

I created the following query:

StudentsGrades.GroupBy(student => student.Name)
    .OrderBy(studentGradesGroup => studentGradesGroup.Max(student => student.Grade));

But that returns IEnumerable IGrouping, and I have no way to sort the list inside, unless I do that in another foreach query and add the results to a different list using AddRange.

Is there a prettier way to do that?

Answer

Jon Skeet picture Jon Skeet · Feb 16, 2011

Sure:

var query = grades.GroupBy(student => student.Name)
                  .Select(group => 
                        new { Name = group.Key,
                              Students = group.OrderByDescending(x => x.Grade) })
                  .OrderBy(group => group.Students.First().Grade);

Note that you can get away with just taking the first grade within each group after ordering, because you already know the first entry will be have the highest grade.

Then you could display them with:

foreach (var group in query)
{
    Console.WriteLine("Group: {0}", group.Name);
    foreach (var student in group.Students)
    {
        Console.WriteLine("  {0}", student.Grade);
    }
}