Порядок LINQ и, группы и каждой группе?
у меня есть объект, который выглядит примерно так:
public class Student
{
public string Name { get; set; }
public int Grade { get; set; }
}
Я хотел бы создать следующий запрос: группируйте оценки по имени студента, упорядочивайте каждую группу студентов по классам и упорядочивайте группы по максимальному классу в каждой группе.
так это будет выглядеть так:
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));
но это возвращает IEnumerableIGrouping, и у меня нет способа отсортировать список внутри, если я не сделаю это в другом foreach запрос и добавьте результаты в другой список с помощью AddRange.
есть ли более красивый способ сделать это?
5 ответов:
обязательно:
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); } }
Я думаю, что вы хотите дополнительную проекцию, которая отображает каждую группу в сортированную версию группы:
.Select(group => group.OrderByDescending(student => student.Grade))
Он также выглядит как вы может хотите еще одну операцию выравнивания после этого, которая даст вам последовательность студентов вместо последовательности групп:
.SelectMany(group => group)вы всегда можете свернуть в один
SelectManyвызов, который делает проекцию и сглаживание вместе.
изменить: Как Джон Скит указывает, что в общем запросе есть определенные недостатки; информация, полученная от сортировки каждой группы, не используется при упорядочении самих групп. Перемещая сортировку каждой группы, чтобы прийти до порядок самих групп, то
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)) { ------------------------ -------------------------- } }
Comments