2011-02-16 52 views
49

我有一个对象,它看起来是这样的: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将结果添加到其他列表中。

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

回答

101

肯定的:

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

有对VAR组变量没有关键属性。 –

+0

@David B:哎呦,修正了。 –

+2

谢谢!这是完成的查询 - studentGrades.GroupBy(student => student.Name) 。选择(group => new {Students = group.OrderByDescending(x => x.Grade)}) .OrderByDescending(group => group。 Students.First()。Grade) .SelectMany(group => group.Students) – Rita

10

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

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

它还看起来像你可能想要在此之后的另一个展平操作,这将给你一个学生序列,而不是一个序列组:

.SelectMany(group => group) 

您可以随时坍塌两成SelectMany调用,它的投影和压扁在一起。


编辑: 作为乔恩斯基特指出的,在整个查询某些低效率;从排序每个组获得的信息并未用于组自身的排序。通过将每个组的排序移动到之前组的排序本身,Max查询可以躲避到更简单的First查询中。

+1

非常感谢! – Rita

+0

太棒了,谢谢! –

3

试试这个......

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

做才不至于投影方式:

StudentsGrades.OrderBy(student => student.Name). 
ThenBy(student => student.Grade); 
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)) 
     { 
      ------------------------ 
      -------------------------- 
     } 
    }