Свободная сортировка List<T> по нескольким критериям с использованием методов расширения?
-
03-07-2019 - |
Вопрос
Чтобы отсортировать список по нескольким критериям, я сейчас делаю что-то вроде:
collection.Sort((f1, f2) =>
{
var comp = f1.FirstCriteria.CompareTo(f2.FirstCriteria);
return comp != 0 ? comp : f1.SecondCriteria.CompareTo(f2. SecondCriteria);
});
Но было бы неплохо иметь возможность сделать что-то вроде:
collection.MultipleSort(f1.FirstCriteria, f2.FirstCriteria)
.Then(f1.SecondCriteria, f2.SecondCriteria)
Есть идеи по хорошей реализации гибкого интерфейса сортировки?
Решение
Вы имеете в виду что-то вроде следующего?
using System.Linq;
collection.OrderBy(t => t.FirstCriteria).ThenBy(t => t.SecondCriteria);
Другие советы
Проблема здесь в том, что это звучит так, будто вы хотите сделать на месте Сортировать;в этом случае вам нужно будет знать (с помощью свободного API), когда вы закончите добавлять условия.Это контрастирует с подходом LINQ, поскольку в нем используется отложенное выполнение.
Для сортировки по одному условию вы можете использовать что-то вроде:
public static void Sort<TSource, TValue>(this List<TSource> source,
Func<TSource, TValue> selector) {
var comparer = Comparer<TValue>.Default;
source.Sort((x,y)=>comparer.Compare(selector(x),selector(y)));
}
public static void SortDescending<TSource, TValue>(this List<TSource> source,
Func<TSource, TValue> selector) {
var comparer = Comparer<TValue>.Default;
source.Sort((x,y)=>comparer.Compare(selector(y),selector(x)));
}
С несколькими сортами было бы сложнее;ты не можешь использовать params
потому что каждый TValue
может быть разным.Вероятно, вам придется либо использовать шаг терминатора и промежуточный класс «строитель» (по сути, написание DSL), либо вам придется сначала создать компаратор отдельно.