По возрастанию/убыванию в LINQ - можно изменить порядок через параметр?
У меня есть метод, которому задан параметр "bool sortAscending". Теперь я хочу использовать LINQ для создания отсортированного списка в зависимости от этого параметра. Я получил следующее:
var ascendingQuery = from data in dataList
orderby data.Property ascending
select data;
var descendingQuery = from data in dataList
orderby data.Property descending
select data;
Как вы можете видеть, оба запроса отличаются только "восходящим" или. "По убыванию". Я хотел бы объединить оба запроса, но я не знаю, как это сделать. Кто-нибудь имеет ответ?
Ответы
Ответ 1
Вы можете легко создать свой собственный метод расширения в IEnumerable или IQueryable:
public static IOrderedEnumerable<TSource> OrderByWithDirection<TSource,TKey>
(this IEnumerable<TSource> source,
Func<TSource, TKey> keySelector,
bool descending)
{
return descending ? source.OrderByDescending(keySelector)
: source.OrderBy(keySelector);
}
public static IOrderedQueryable<TSource> OrderByWithDirection<TSource,TKey>
(this IQueryable<TSource> source,
Expression<Func<TSource, TKey>> keySelector,
bool descending)
{
return descending ? source.OrderByDescending(keySelector)
: source.OrderBy(keySelector);
}
Да, вы теряете возможность использовать выражение запроса здесь, но, откровенно говоря, я не думаю, что вы в любом случае выигрываете от выражения запроса. Выражения запросов отлично подходят для сложных вещей, но если вы выполняете только одну операцию, проще просто выполнить одну операцию:
var query = dataList.OrderByWithDirection(x => x.Property, direction);
Ответ 2
В терминах того, как это реализовано, это изменяет метод - от OrderBy/ThenBy до OrderByDescending/ThenByDescending. Однако вы можете применить сортировку отдельно к основному запросу...
var qry = from .... // or just dataList.AsEnumerable()/AsQueryable()
if(sortAscending) {
qry = qry.OrderBy(x=>x.Property);
} else {
qry = qry.OrderByDescending(x=>x.Property);
}
Любое использование? Вы можете создать весь "заказ" динамически, но он более задействован...
Другой трюк (в основном соответствующий LINQ-to-Objects) заключается в использовании множителя -1/1. Это действительно полезно для числовых данных, но это навязчивый способ достичь того же результата.
Ответ 3
Как насчет упорядочения desc по желаемому свойству,
blah = blah.OrderByDescending(x => x.Property);
И затем сделав что-то вроде
if (!descending)
{
blah = blah.Reverse()
}
else
{
// Already sorted desc ;)
}
Слишком медленный режим Reverse()?
Ответ 4
В дополнение к красивому решению, данному @Jon Skeet, мне также нужны были ThenBy и ThenByDescending, поэтому я добавляю его на основе его решения:
public static IOrderedEnumerable<TSource> ThenByWithDirection<TSource, TKey>(
this IOrderedEnumerable<TSource> source,
Func<TSource, TKey> keySelector,
bool descending)
{
return descending ?
source.ThenByDescending(keySelector) :
source.ThenBy(keySelector);
}