In LINQ, is it possible to have conditional orderby sort order (ascending vs. descending).
Something like 开发者_StackOverflowthis (not valid code):
bool flag;
(from w in widgets
where w.Name.Contains("xyz")
orderby w.Id (flag ? ascending : descending)
select w)
If you build the expression incrementally you can do this. Generally easier using expressions rather than comprehension expressions:
var x = widgets.Where(w => w.Name.Contains("xyz"));
if (flag) {
x = x.OrderBy(w => w.property);
} else {
x = x.OrderByDescending(w => w.property);
}
(Assuming the Widget's property
is basis of sort since you don't list one.)
...Or do it all in one statement
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;
Here is a more general solution, that can be used for various conditional lambda expressions without breaking the flow of the 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);
}
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));
You can define a base query without the ordering, then order according to the flag:
var query=(from w in widgets
where w.Name.Contains("xyz")
select w);
var result = flag ?
query.OrderBy(w =>w) :
query.OrderByDescending(w = w);
You could try something like the following:
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);
If the ordering property Id
is a number (or supports the unary minus) one could also do:
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 ...
The MoreLINQ NuGet package also provides extension methods to make this more convenient. It also provides many more helpful extension methods and is therefore a stable go-to in my projects.
Can also roll up Richard's answer into a convenient helper method, like so:
internal static class LinqExtensions
{
public static IOrderedEnumerable<TSource> OrderBy<TSource,TKey>
(this IEnumerable<TSource> source,
Func<TSource, TKey> keySelector,
bool ascending)
{
return ascending ? source.OrderBy(keySelector)
: source.OrderByDescending(keySelector);
}
public static IOrderedEnumerable<TSource> ThenBy<TSource,TKey>
(this IOrderedEnumerable<TSource> source,
Func<TSource, TKey> keySelector,
bool ascending)
{
return ascending ? source.ThenBy(keySelector)
: source.ThenByDescending(keySelector);
}
}
You can even do more complex ordering and still keep it short:
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);
精彩评论