Сортировка списка в .Net по одному полю, затем другому - PullRequest
2 голосов
/ 25 февраля 2011

У меня есть список объектов, которые мне нужно отсортировать на основе некоторых их свойств.Это прекрасно работает для сортировки по одному полю:

reportDataRows.Sort((x, y) => x["Comment1"].CompareTo(y["Comment1"]));
foreach (var row in reportDataRows) {
   ...
}

Здесь я вижу множество примеров, которые делают это только с одним полем.Но как мне отсортировать по одному полю, а затем по другому?Или как насчет списка многих полей?Похоже, что лучше использовать LINQ orderby, но я не знаю достаточно об этом, чтобы знать, как его использовать.

Для параметров что-то вроде этого, поддерживающее любое количество полей для сортировки, будетприятно:

var sortBy = new List<string>(){"Comment1","Time"};

Я не хочу писать код, чтобы делать это в каждом из моих приложений.Я планирую перенести этот код сортировки в класс, содержащий данные, чтобы он мог выполнять более сложные задачи, такие как использование списка параметров и неявное распознавание того, что поле является датой, и сортировка его как даты вместо строки.Объект reportDataRow содержит поля с этой информацией, поэтому мне не нужно делать никаких грязных проверок, чтобы выяснить, должно ли поле быть датой.

Ответы [ 7 ]

7 голосов
/ 25 февраля 2011

Да, я думаю, что имеет смысл использовать OrderBy и ThenBy:

foreach (var row in reportDataRows.OrderBy(x => x["Comment1"]).ThenBy(x => x["Comment2"]) 
{
    ...
}

Предполагается, что другая вещь, которую вы хотите заказать, это "Comment2".

2 голосов
/ 25 февраля 2011

Попробуйте это:

reportDataRows.Sort((x, y) =>
{
    var compare = x["Comment1"].CompareTo(y["Comment1"]);
    if(compare != 0)
        return compare;

    return x["Comment2"].CompareTo(y["Comment2"]);
});
1 голос
/ 25 февраля 2011

Возможно, вы захотите взглянуть на этот предыдущий ответ , где я разместил метод расширения, который обрабатывает несколько заказов в LINQ.Это позволяет такой синтаксис:

myList.OrderByMany(x => x.Field1, x => x.Field2);
1 голос
/ 25 февраля 2011

Посмотрите на пример для ThenBy в msdn.

0 голосов
/ 25 февраля 2011

С использованием синтаксиса метода LINQ:

var sortedRows = reportDataRows.OrderBy(r => r["Comment1"])
                   .ThenBy(r => r["AnotherField"];

foreach (var row in sortedRows) {
   ...
}

И даже более читабельно при использовании синтаксиса понимания запросов:

var sortedRows = from r in reportDataRows
                 orderby r["Comment1"], r["Comment2"]
                 select r;
foreach (var row in sortedRows) {
   ...
}
0 голосов
/ 25 февраля 2011

Вы получили это. Enumerable.OrderBy (). ThenBy () - ваш билет. Это работает так же, как выглядит; элементы сортируются по каждой проекции, а связи определяются путем сравнения следующей проекции. Вы можете связать столько цепочек ThenBys, сколько хотите, и есть также методы OrderByDesc и ThenByDesc, которые будут сортировать эту проекцию в порядке убывания.

Как отметил Альбин, цепочка OrderBy не касается исходного списка, пока вы не присвойте результат упорядочения обратно исходной переменной, например:

reportDataRows = reportDataRows.OrderBy(x=>x.Comment1).ThenBy(x=>x.Comment2).ToList();

Как правило, OrderBy будет работать немного медленнее, чем List.Sort (); Алгоритм предназначен для работы с любой серией элементов IEnumerable, поэтому для сортировки (которая требует знания каждого элемента серии) он отбрасывает весь свой перечисляемый источник в новый массив. Тем не менее, OrderBy имеет явное преимущество перед Sort в том смысле, что это «стабильная» сортировка; элементы, которые в точности равны друг другу, сохранят свой «относительный порядок» в отсортированном перечислимом (первый из двух, с которыми вы столкнетесь при итерации по несортированному списку, будет первым из двух, встречающихся при переборе по отсортированному списку ).

0 голосов
/ 25 февраля 2011

Если вы сравниваете свои собственные объекты, вы можете реализовать интерфейс IComparable .В противном случае вы можете использовать интерфейс IComparer .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...