2012-01-27 15 views
14

Mam zagnieżdżonej listy,OrderBy/ThenBy zapętlenie - zagnieżdżonych list w C#

List<List<String>> intable; 

gdzie chciałbym uporządkować wszystkie kolumny. Problem polega na tym, że liczba kolumn zależy od danych wprowadzanych przez użytkownika.

Sortowanie listy jak to działa prawidłowo (przy założeniu 4 kolumny w tym przykładzie)

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

ale kiedy kładę go w pętli, podobnie jak to:

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

go już nie działa poprawnie i sortuje tylko czwartą kolumnę.

+1

Zobacz ten [http://social.msdn.microsoft .pl/forum/en-US/linqprojectgeneral/thread/61e502b4-6795-4e51-b70e-2be642cfc413 /] (http://social.msdn.microsoft.com/forums/en-US/linqprojectgeneral/thread/61e502b4-6795 -4e51-b70e-2be642cfc413 /) –

Odpowiedz

24

Jest to przypadek dostępu do zmodyfikowanego zamknięcia. Zmień kod do tego i to będzie działać:

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 napisał two-part article opisując problem. Powód, dla którego nie działa tak, jak oczekujesz, w skrócie - ponieważ LINQ używa tylko ostatniej wartości i, gdy jest oceniany, gdy zadzwonisz pod numer ToList(). To samo jakbyś napisał:

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 potwierdził, że zachowanie zamknięcia zmieni się w C# 5. [SO Link Here] (http://stackoverflow.com/a/8899347/498969) –

+6

@AdamSpicer: Nie zmieni się dla pętli "dla", tylko dla pętli "foreach". –

+0

@EricLippert, dzięki za wyjaśnienie! –

0

Tworzenie porównywarka

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

następnie posortować listę jak ten

intable.Sort(new StringListComparer()); 
Powiązane problemy