2009-10-22 17 views
22

En LINQ, es posible tener orden condicional por orden de clasificación (ascendente vs. descendente).Orden de clasificación "orderby" condicional en LINQ

Algo como esto (código no válido):

bool flag; 

(from w in widgets 
where w.Name.Contains("xyz") 
orderby w.Id (flag ? ascending : descending) 
select w) 

Respuesta

25

Si se construye la expresión de forma incremental que puede hacer esto. Generalmente es más fácil el uso de expresiones en lugar de expresiones de comprensión:

var x = widgets.Where(w => w.Name.Contains("xyz")); 
if (flag) { 
    x = x.OrderBy(w => w.property); 
} else { 
    x = x.OrderByDescending(w => w.property); 
} 

(. Suponiendo del Widget property es base de la especie ya que no anota uno)

+0

cómo se consiguen múltiples pedidos con condiciones dinámicas si se requieren o no. – Ruchan

+0

Solo necesita usar una variable diferente para el resultado de 'OrderBy' y' ThenBy' para mantener el tipo de devolución diferente; de lo contrario, simplemente agregue llamadas al operador LINQ correspondiente 'ThenBy' o 'ThenByDescending'. – Richard

8

Puede definir una consulta de base sin el pedido, entonces el orden de acuerdo a la bandera:

var query=(from w in widgets 
    where w.Name.Contains("xyz") 
    select w); 

var result = flag ? 
    query.OrderBy(w =>w) : 
    query.OrderByDescending(w = w); 
8

usted podría intentar algo como lo siguiente:

var q = from i in list 
     where i.Name = "name" 
     select i; 
if(foo) 
    q = q.OrderBy(o=>o.Name); 
else 
    q = q.OrderByDescending(o=>o.Name); 
14

... o hacerlo todo en un comunicado

bool flag; 

var result = from w in widgets where w.Name.Contains("xyz") 
    orderby 
    flag ? w.Id : 0, 
    flag ? 0 : w.Id descending 
    select w; 
+0

Si los datos subyacentes están en SQL, esta respuesta parece ser la más probable para utilizar la cláusula ORDERBY de SQL, pero no lo sé con certeza. –

1

Si la propiedad de ordenación Id es un número (o apoya la menos unario) también se podría hacer:

bool ascending = ... 

collection.Where(x => ...) 
    .OrderBy(x => ascending ? x.Id : -x.Id) 
    .Select(x => ...) 

// LINQ query 
from x in ... 
orderby (ascending ? x.Id : -x.Id) 
select ... 
0

El MoreLINQ NuGet package también proporciona métodos de extensión para hacer que this sea más conveniente. También proporciona muchos más métodos de extensión útiles y, por lo tanto, es un objetivo estable en mis proyectos.

3

Aquí hay una solución más general, que se puede usar para varias expresiones lambda condicional sin interrumpir el flujo de la expresión.

public static IEnumerable<T> IfThenElse<T>(
    this IEnumerable<T> elements, 
    Func<bool> condition, 
    Func<IEnumerable<T>, IEnumerable<T>> thenPath, 
    Func<IEnumerable<T>, IEnumerable<T>> elsePath) 
{ 
    return condition() 
     ? thenPath(elements) 
     : elsePath(elements); 
} 

e.g.

var result = widgets 
    .Where(w => w.Name.Contains("xyz")) 
    .IfThenElse(
     () => flag, 
     e => e.OrderBy(w => w.Id), 
     e => e.OrderByDescending(w => w.Id)); 
0

Usted puede incluso hacer pedidos más complejo y todavía que sea breve:

var dict = new Dictionary<int, string>() { [1] = "z", [3] = "b", [2] = "c" }; 
    var condition = true; 
    var result = (condition ? dict.OrderBy(x => x.Key) : dict.OrderByDescending(x => x.Value)) 
     .Select(x => x.Value);