Question

I have a list of Func defining an ordering:

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

I can order the results with something like...

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

I'm trying to figure how to do the above when the list can contain any number of sequential orderings. Is it possible?

Was it helpful?

Solution

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

is the same as

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

so you simply write a loop like this:

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

OTHER TIPS

As others have mentioned, you can use a loop to do this.

If you prefer, you can also use the Aggregate operator:

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

(or)

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

You should be able to do something similar to this

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

Alternately

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

Remember that LINQ execution is deferred. You can build up the expression sequentially before accessing the results, doing something like:

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

You might want to do this with dynamically building up you're expression. More info here: Dynamic LINQ and Dynamic Lambda expressions?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top