2011-09-06 10 views
5

Tengo una lista de Func definir un ordenamiento:LINQ a objetos que ordenan por número arbitrario de parámetros

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

puedo ordenar los resultados con algo así como ...

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

estoy tratando de averiguar cómo hacer lo anterior cuando la lista puede contener cualquier cantidad de ordenamientos secuenciales. ¿Es posible?

Respuesta

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

es la misma que

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

por lo que simplemente escribe un bucle como este:

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

que realmente no necesita para comprobar si hay un recuento, si sólo cambia lo que está siendo hecho en el bucle – msarchet

+0

No me di cuenta de que el bit "es lo mismo" era cierto por alguna razón. Pensé que tenían que seguir directamente. Muchas gracias. – fearofawhackplanet

+0

hmmmm ... en realidad no son lo mismo. 'ThenBy' opera en un' OrderedEnumerable ', que es como lo recordaba. Creo que puedo evitar eso sin embargo. – fearofawhackplanet

3

Usted debe ser capaz de hacer algo similar a esto

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

Recuerde que la ejecución de LINQ se aplaza. Se puede construir hasta la expresión secuencial antes de acceder a los resultados, haciendo algo como:

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

Como otros han mencionado, se puede utilizar un bucle para hacer esto.

Si lo prefiere, también puede utilizar el Aggregate operador:

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

(o)

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

Me gusta la concisión de estos, gracias – fearofawhackplanet

Cuestiones relacionadas