2011-09-06 46 views
5

我有Func定義排序列表:LINQ到對象通過參數任意數量的訂貨

var ordering = new List<Func<Person, IComparable>> 
       { x => x.Surname, x => x.FirstName }; 

我可以訂購類似的結果...

people = people.OrderBy(ordering[0]).ThenBy(ordering[1]); 

我當列表可以包含任意數量的順序排序時,試圖找出如何進行上述操作。可能嗎?

回答

6
people = people.OrderBy(ordering[0]).ThenBy(ordering[1]).ThenBy(ordering[2]); 

相同

var orderedPeople = people.OrderBy(ordering[0]); 
orderedPeople = orderedPeople.ThenBy(ordering[1]); 
orderedPeople = orderedPeople.ThenBy(ordering[2]); 
people = orderedPeople; 

,所以你只要寫一個像這樣的循環:

if (ordering.Count != 0) 
{ 
    var orderedPeople = people.OrderBy(ordering[0]); 
    for (int i = 1; i < ordering.Count; i++) 
    { 
     orderedPeople = orderedPeople.ThenBy(ordering[i]); 
    } 
    people = orderedPeople; 
} 
+0

你其實並不需要檢查計數,如果你只是切換什麼是在循環中完成 – msarchet

+0

我沒有意識到「是一樣的」由於某種原因,位是真的。我認爲他們必須直接跟蹤。非常感謝。 – fearofawhackplanet

+0

嗯......其實他們是不一樣的。 'ThenBy'運行在'OrderedEnumerable '上,這就是我記憶中的方式。我想我可以解決這個問題。 – fearofawhackplanet

3

你應該能夠做到類似這樣

東西
people = people.OrderBy(ordering[0]) 
foreach(var order in ordering.Skip(1)) 
{ 
    people = people.ThenBy(order); 
} 

Al ternately

for(i = 0; i < ordering.Count; i++) 
{ 
    people = i == 0 ? people.OrderBy(ordering[i]) : people.ThenBy(ordering[i]); 
} 
2

請記住,LINQ執行被延期。您可以訪問的結果,做這樣的事情之前建立的表達順序:

var ordered = unordered.OrderBy(ordering.First()); 
foreach (var orderingItem in ordering.Skip(1)) 
{ 
    ordered = ordered.ThenBy(orderingItem); 
} 
4

正如其他人所說,你可以使用一個循環做到這一點。

如果你願意,你也可以使用Aggregate操作:

// Requires a non-empty ordering sequence. 
var result2 = ordering.Skip(1) 
         .Aggregate(people.OrderBy(ordering.First()), Enumerable.ThenBy); 

(或)

// Shorter and more "symmetric" but potentially more inefficient. 
// x => true should work because OrderBy is a stable sort. 
var result = ordering.Aggregate(people.OrderBy(x => true), Enumerable.ThenBy); 
+1

我喜歡這些簡潔,謝謝 – fearofawhackplanet