Linq排序依据,分组依据和各组排序?


73

我有一个看起来像这样的对象:

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

但这返回了IEnumerable IGrouping,并且我无法对列表进行排序,除非在另一个foreach查询中执行此操作,然后使用将结果添加到其他列表中AddRange

有没有更漂亮的方法可以做到这一点?

Answers:


139

当然:

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

3
该var组变量上没有Key属性。
艾米B

5
谢谢!这是完成的查询-studentGrades.GroupBy(student => student.Name).Select(group => new {学生= group.OrderByDescending(x => x.Grade)}).OrderByDescending(group => group.Students。 First()。Grade).SelectMany(group => group.Students)
丽塔(Rita

20

无需投影的方式:

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

3
我认为这是因为尽管它会按要求对数据进行排序,但这是偶然的。表现最好的学生也按字母顺序排列。如果您给学生C的分数是90,则他们应该显示在学生B之上。在这个答案中,他们不会。
红色:

14

我认为您需要一个额外的投影,将每个组映射到该组的排序版本:

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

这似乎也像你可能想后,另一扁平化操作,这将给你的学生,而不是组序列的序列:

.SelectMany(group => group)

您始终可以将它们折叠成一个单独的 SelectMany调用,以一起进行投影和展平。


编辑:正如乔恩·斯凯特(Jon Skeet)所指出的那样,整个查询中存在某些效率低下的问题;从排序每个组获得的信息未用于组本身的排序。通过将每个组的排序移到组本身的排序之前Max可以将查询规避为更简单的First查询。


5

尝试这个...

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

1

或者,您可以这样做:

     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))
        {
           ------------------------
           --------------------------
        }
     }
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.