2012-01-27 73 views
14

tôi có một danh sách lồng nhau,OrderBy/ThenBy looping - Danh sách lồng nhau trong C#

List<List<String>> intable; 

nơi tôi muốn sắp xếp tất cả các cột. Vấn đề là số lượng cột phụ thuộc vào đầu vào của người dùng.

Phân loại danh sách như thế này hoạt động tốt (giả sử 4 cột ví dụ này)

var tmp = intable.OrderBy(x => x[0]); 
tmp = tmp.ThenBy(x => x[1]); 
tmp = tmp.ThenBy(x => x[2]); 
tmp = tmp.ThenBy(x => x[3]); 
intable = tmp.ToList(); 

Nhưng, khi tôi đặt nó trong một vòng lặp, như thế này:

var tmp = intable.OrderBy(x => x[0]); 
for (int i = 1; i <= 3; i++) 
{ 
     tmp = tmp.ThenBy(x => x[i]); 
} 
intable = tmp.ToList(); 

nó hoạt động không còn một cách chính xác và chỉ sắp xếp cột thứ tư.

+1

Xem này [http://social.msdn.microsoft .com/forums/vi-US/linqprojectgeneral/thread/61e502b4-6795-4e51-b70e-2be642cfc413 /] (http://social.msdn.microsoft.com/forums/en-US/linqprojectgeneral/thread/61e502b4-6795 -4e51-b70e-2be642cfc413 /) –

Trả lời

24

Đây là trường hợp của quyền truy cập vào một đóng cửa đã sửa đổi. Thay đổi mã này và nó sẽ hoạt động:

var tmp = intable.OrderBy(x => x[0]); 
for (int i = 1; i <= 3; i++) { 
    var thisI = i; 
    tmp = tmp.ThenBy(x => x[thisI]); 
} 
intable = tmp.ToList(); 

Eric Lippert viết two-part article mô tả sự cố. Lý do nó không hoạt động như bạn mong đợi - ngắn gọn - bởi vì LINQ chỉ sử dụng giá trị cuối cùng của i khi nó được đánh giá khi bạn gọi ToList(). Nó giống như nếu bạn đã viết:

var tmp = intable.OrderBy(x => x[0]); 
tmp = tmp.ThenBy(x => x[3]); 
tmp = tmp.ThenBy(x => x[3]); 
tmp = tmp.ThenBy(x => x[3]); 
intable = tmp.ToList(); 
+5

Eric Lippert đã xác nhận rằng hành vi đóng cửa sẽ thay đổi trong C# 5. [SO Liên kết ở đây] (http://stackoverflow.com/a/8899347/498969) –

+6

@AdamSpicer: Nó sẽ không thay đổi cho "cho" vòng, chỉ cho vòng "foreach". –

+0

@EricLippert, Cảm ơn bạn đã làm rõ! –

0

Tạo một Comparer

class StringListComparer : IComparer<List<string>> 
{ 
    public int Compare(List<string> x, List<string> y) 
    { 
     int minLength = Math.Min(x.Count, y.Count); 
     for (int i = 0; i < minLength; i++) { 
      int comp = x[i].CompareTo(y[i]); 
      if (comp != 0) { 
       return comp; 
      } 
     } 
     return x.Count.CompareTo(y.Count); 
    } 
} 

sau đó sắp xếp danh sách như thế này

intable.Sort(new StringListComparer()); 
Các vấn đề liên quan