Linq to Objects упорядочение по произвольному количеству параметров - PullRequest
5 голосов
/ 06 сентября 2011

У меня есть список Func, определяющий порядок:

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

Я могу заказать результаты с чем-то вроде ...

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

Я пытаюсь понять, как это сделать, когда список может содержать любое количество последовательных порядков. Возможно ли это?

Ответы [ 5 ]

6 голосов
/ 06 сентября 2011
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;

, поэтому вы просто пишете цикл следующим образом:

4 голосов
/ 06 сентября 2011

Как уже упоминалось, вы можете использовать цикл для этого.

Если вы предпочитаете, вы также можете использовать оператор 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);
3 голосов
/ 06 сентября 2011

Вы должны быть в состоянии сделать что-то похожее на это

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

поочередно

 for(i = 0; i < ordering.Count; i++)
 {
    people = i == 0 ? people.OrderBy(ordering[i]) : people.ThenBy(ordering[i]);
 }
2 голосов
/ 06 сентября 2011

Помните, что выполнение LINQ отложено. Вы можете создать выражение последовательно перед доступом к результатам, выполнив что-то вроде:

var ordered = unordered.OrderBy(ordering.First());
foreach (var orderingItem in ordering.Skip(1))
{
    ordered = ordered.ThenBy(orderingItem);
}
0 голосов
/ 06 сентября 2011

Возможно, вы захотите сделать это с помощью динамического наращивания выражения.Более подробная информация здесь: Динамические выражения LINQ и Dynamic Lambda?

...