web-dev-qa-db-fra.com

Ordre de tri conditionnel "ordre par" dans LINQ

Dans LINQ, est-il possible d'avoir un ordre conditionnel selon un ordre de tri (croissant ou décroissant).

Quelque chose comme ça (code non valide):

bool flag;

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

Si vous construisez l'expression progressivement, vous pouvez le faire. Généralement plus facile en utilisant des expressions plutôt que des expressions de compréhension:

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

(En supposant que la variable property du widget soit une base de tri puisque vous n'en indiquez pas une.)

27
Richard

... Ou tout faire en une seule déclaration

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;
17
Carter Medlin

Vous pouvez définir une requête de base sans la commande, puis la commande en fonction du drapeau:

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
Konamiman

Vous pouvez essayer quelque chose comme ce qui suit:

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);
8
cloggins

Voici une solution plus générale, qui peut être utilisée pour diverses expressions lambda conditionnelles sans interrompre le flux de l’expression.

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

par exemple.

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

Si la propriété de commande Id est un nombre (ou prend en charge le moins unaire), vous pouvez également:

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 ...
2
Julian Lettner

Le paquet MoreLINQ NuGet package fournit également des méthodes d’extension pour rendre this plus pratique. Il fournit également beaucoup plus de méthodes d'extension utiles et constitue par conséquent une solution stable dans mes projets.

1
Julian Lettner

Vous pouvez même effectuer des commandes plus complexes tout en restant bref:

    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);
0
watbywbarif