Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Linq to Objects ordering by arbitrary number of parameters

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?

like image 806
fearofawhackplanet Avatar asked Sep 06 '11 16:09

fearofawhackplanet


3 Answers

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;
}
like image 125
dtb Avatar answered Nov 13 '22 14:11

dtb


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);
like image 4
Ani Avatar answered Nov 13 '22 12:11

Ani


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]);
 }
like image 3
msarchet Avatar answered Nov 13 '22 13:11

msarchet