2011-02-16 42 views
49

Tôi có một đối tượng mà trông giống như sau:Đặt hàng LINQ theo, nhóm và sắp xếp theo từng nhóm?

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

Tôi muốn tạo ra các truy vấn sau đây: lớp nhóm theo tên sinh viên, ra lệnh cho từng nhóm sinh viên của lớp, và các nhóm tự do lớp tối đa trong mỗi nhóm .

Vì vậy, nó sẽ giống như thế này:

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

tôi tạo ra các truy vấn sau đây:

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

Nhưng đó trả về IEnumerableIGrouping, và tôi không có cách nào để sắp xếp danh sách bên trong, trừ khi tôi làm điều đó trong một truy vấn foreach khác và thêm kết quả vào danh sách khác bằng cách sử dụng AddRange.

Có cách nào đẹp hơn để làm điều đó không?

Trả lời

101

chắc:

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

Lưu ý rằng bạn có thể nhận được ngay với chỉ lấy lớp đầu tiên trong mỗi nhóm sau khi đặt hàng, vì bạn đã biết sự xâm nhập đầu tiên sẽ được có bậc cao nhất.

Sau đó, bạn có thể hiển thị chúng với:

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

Không có thuộc tính Key trên rằng biến var nhóm. –

+0

@David B: Rất tiếc, đã được sửa. –

+2

Cảm ơn bạn! Đây là truy vấn đã hoàn thành - studentGrades.GroupBy (student => student.Name) .Chọn (group => new {Students = group.OrderByDescending (x => x.Grade)}) .OrderByDescending (group => group. Students.First(). Lớp) .SelectMany (group => group.Students) – Rita

10

Tôi nghĩ rằng bạn muốn có một dự báo bổ sung bản đồ mỗi nhóm một được sắp xếp phiên bản của nhóm:

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

Nó cũng xuất hiện như bạn có thể muốn có một thao tác làm phẳng khác sau đó sẽ cung cấp cho bạn một chuỗi các sinh viên thay vì một chuỗi các nhóm:

.SelectMany(group => group) 

Bạn luôn có thể sụp đổ cả vào một cuộc gọi đơnSelectMany mà không được công chiếu và làm phẳng với nhau.


EDIT: Như Jon Skeet chỉ ra, có một số sự thiếu hiệu quả trong truy vấn tổng thể; thông tin thu được từ việc phân loại từng nhóm không được sử dụng theo thứ tự của các nhóm. Bằng cách di chuyển sắp xếp của mỗi nhóm để đến trước khi thứ tự của các nhóm, truy vấn Max có thể được né tránh thành truy vấn đơn giản hơn First.

+1

Cảm ơn bạn rất nhiều! – Rita

+0

Tuyệt vời, cảm ơn bạn! –

3

hãy thử điều này ...

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

Cách để làm điều đó mà không cần chiếu:

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

Hoặc bạn có thể làm như thế này:

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