Linqsorting,按组sorting?

我有一个像这样的对象:

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

我想创build以下查询:按学生姓名分组成绩,按年级排列每个学生组,按每组最高成绩排列组。

所以它会看起来像这样:

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

我创build了以下查询:

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

但是,这返回IEnumerable IGrouping ,我没有办法sorting列表里面,除非我这样做在另一个foreach查询,并使用AddRange将结果添加到不同的列表。

有没有更好的方法来做到这一点?

当然:

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

请注意,您可以在订购后在每个小组中拿到一年级,因为您已经知道第一次入学的成绩是最高的。

然后你可以显示他们:

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

我想你想要一个额外的投影,将每个组映射到组的sorting版本:

 .Select(group => group.OrderByDescending(student => student.Grade)) 

这也看起来像你可能想在此之后的另一个扁平化操作,这将给你一连串的学生,而不是一连串的组:

 .SelectMany(group => group) 

您始终可以将两者都折叠为一个SelectMany调用,它可以将投影和拼合在一起。


编辑:正如乔恩Skeet指出,整体查询有一定的低效率; 从sorting每个组获得的信息没有被用于组自己的sorting。 通过将每个组的sorting移动到组本身的sorting之前Max查询可以躲避到更简单的First查询中。

没有投影的方法:

 StudentsGrades.OrderBy(student => student.Name). ThenBy(student => student.Grade); 

尝试这个…

 public class Student { public int Grade { get; set; } public string Name { get; set; } public override string ToString() { return string.Format("Name{0} : Grade{1}", Name, Grade); } } class Program { static void Main(string[] args) { List<Student> listStudents = new List<Student>(); listStudents.Add(new Student() { Grade = 10, Name = "Pedro" }); listStudents.Add(new Student() { Grade = 10, Name = "Luana" }); listStudents.Add(new Student() { Grade = 10, Name = "Maria" }); listStudents.Add(new Student() { Grade = 11, Name = "Mario" }); listStudents.Add(new Student() { Grade = 15, Name = "Mario" }); listStudents.Add(new Student() { Grade = 10, Name = "Bruno" }); listStudents.Add(new Student() { Grade = 10, Name = "Luana" }); listStudents.Add(new Student() { Grade = 11, Name = "Luana" }); listStudents.Add(new Student() { Grade = 22, Name = "Maria" }); listStudents.Add(new Student() { Grade = 55, Name = "Bruno" }); listStudents.Add(new Student() { Grade = 77, Name = "Maria" }); listStudents.Add(new Student() { Grade = 66, Name = "Maria" }); listStudents.Add(new Student() { Grade = 88, Name = "Bruno" }); listStudents.Add(new Student() { Grade = 42, Name = "Pedro" }); listStudents.Add(new Student() { Grade = 33, Name = "Bruno" }); listStudents.Add(new Student() { Grade = 33, Name = "Luciana" }); listStudents.Add(new Student() { Grade = 17, Name = "Maria" }); listStudents.Add(new Student() { Grade = 25, Name = "Luana" }); listStudents.Add(new Student() { Grade = 25, Name = "Pedro" }); listStudents.GroupBy(g => g.Name).OrderBy(g => g.Key).SelectMany(g => g.OrderByDescending(x => x.Grade)).ToList().ForEach(x => Console.WriteLine(x.ToString())); } } 

或者你可以这样做:

  var _items = from a in StudentsGrades group a by a.Name; foreach (var _itemGroup in _items) { foreach (var _item in _itemGroup.OrderBy(a=>a.grade)) { ------------------------ -------------------------- } }