Linq按顺序分组,每组按顺序排序?

Rit*_*ita 61 c# linq group-by sql-order-by

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

public class Student
{
    public string Name { get; set; } 
    public int Grade { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

我想创建以下查询:按学生姓名分组成绩,按成绩对每个学生组进行排序,并按每组中的最高成绩对订单组进行排序.

所以它看起来像这样:

A 100
A 80
B 80
B 50
B 40
C 70
C 30
Run Code Online (Sandbox Code Playgroud)

我创建了以下查询:

StudentsGrades.GroupBy(student => student.Name)
    .OrderBy(studentGradesGroup => studentGradesGroup.Max(student => student.Grade));
Run Code Online (Sandbox Code Playgroud)

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

有更漂亮的方法吗?

Jon*_*eet 124

当然:

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);
Run Code Online (Sandbox Code Playgroud)

请注意,您可以在订购后获得每组中的一年级,因为您已经知道第一个条目将具有最高等级.

然后你可以显示它们:

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

  • 谢谢!这是完成的查询 - studentGrades.GroupBy(student => student.Name).Select(group => new {Students = group.OrderByDescending(x => x.Grade)}).OrderByDescending(group => group.Students. First().Grade).SelectMany(group => group.Students) (3认同)
  • 该var组变量没有Key属性. (2认同)

Saw*_*yer 19

没有投影的方法:

StudentsGrades.OrderBy(student => student.Name).
ThenBy(student => student.Grade);
Run Code Online (Sandbox Code Playgroud)

  • 我认为这是因为虽然它会根据要求对数据进行排序,但这是偶然的。表现最好的学生的顺序也是按字母顺序排列的。如果您给学生 C 打 90 分,他们应该出现在学生 B 之上。在这个答案中他们不会。 (3认同)

Ani*_*Ani 15

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

.Select(group => group.OrderByDescending(student => student.Grade))
Run Code Online (Sandbox Code Playgroud)

看起来你可能还需要另外一个展平操作,它会给你一系列学生而不是一系列的组:

.SelectMany(group => group)
Run Code Online (Sandbox Code Playgroud)

您可以随时坍塌两成单一的 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()));
    }
}
Run Code Online (Sandbox Code Playgroud)