Linq упорядочивает, группирует и упорядочивает по каждой группе?

У меня есть объект, который выглядит примерно так:

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

Я хотел бы создать следующий запрос: групповые оценки по имени студента, упорядочить каждую группу студентов по classам и группы заказов по максимальному classу в каждой группе.

Так оно будет выглядеть так:

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

Я создал следующий запрос:

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

Но это возвращает IEnumerable IGrouping , и у меня нет возможности сортировать список внутри, если только я не делаю этого в другом запросе 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); 

Обратите внимание, что после заказа вы можете уйти с первого classа в каждой группе, потому что вы уже знаете, что первая запись будет иметь наивысший class.

Затем вы можете отобразить их с помощью:

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

Я думаю, вам нужна дополнительная проекция, которая отображает каждую группу в отсортированную версию группы:

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

Это также похоже на то, что после этого вам понадобится еще одна операция сглаживания, которая даст вам последовательность учеников вместо последовательности групп:

 .SelectMany(group => group) 

Вы всегда можете свернуть оба в один вызов SelectMany который выполняет проекцию и сплющивание.


EDIT: Как указывает Джон Скит, в общем запросе есть определенные недостатки; информация, полученная при сортировке каждой группы, не используется при упорядочении самих групп. Перемещая сортировку каждой группы до заказа самих групп, запрос 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 listStudents = new List(); 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)) { ------------------------ -------------------------- } } 
  • Медленный запрос при использовании ORDER BY
  • Заказ строк по умолчанию для выбора запроса в oracle
  • Hibernate Named Query Order По параметру
  • GROUP_CONCAT ORDER BY
  • MySQL: Сортировка значений GROUP_CONCAT
  • Пользовательская логика сортировки в OrderBy с использованием LINQ
  • MySQL 'Order By' - сортировка буквенно-цифровых символов
  • Как я могу заказать базу данных SQLITE в порядке убывания, для приложения для Android?
  • Множественный «порядок по» в LINQ
  • Заказ MySQL перед Группой
  • Лучший способ сохранить упорядоченный список в базе данных, сохраняя порядок
  • Давайте будем гением компьютера.