Подтвердить что ты не робот

Сортировка по двум критериям: по возрастанию, по возрастанию

Как я могу выполнить сортировку по двум различным критериям?

Например, у меня есть персональные объекты вроде:

Person со свойствами FirstName (строка), LastName и Rank (int).

Пример таких данных:

Xavier    Smith 1
Alexander Smith 2
Alexander Smith 1
Bob       Hawke 2

Он должен сортировать по первому имени в алфавитном порядке, затем по рангу, например. в результате чего:

Alexander Smith 1
Alexander Smith 2
Bob       Hawke 2
Xavier    Smith 1

До сих пор я пробовал следующее, но он не работает должным образом:

peopleList List<Person>

peopleList.Sort(new Comparison<Person>((x,y) => x.Rank.CompareTo(y.Rank)));
peopleList.Sort(new Comparison<Person>((x, y) => string.Compare(x.Name, y.Name)));

Спасибо

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

peopleList.OrderBy(person => person.FirstName).ThenBy(person => person.Rank).ToList();

Дал бы тот же список, который был правильно отсортирован, правильно?

4b9b3361

Ответ 1

Подход LINQ

С LINQ вы можете использовать OrderBy и ThenBy:

var result = peopleList.OrderBy(p => p.FirstName).ThenBy(p => p.Rank);

Это вернет IEnumerable<T>. Если вам действительно нужно List<T> добавить .ToList() в конец.

Если вы хотите использовать метод Sort, тогда вам нужно будет написать собственный сопоставитель.

EDIT: использование ToList() возвращает новый список. Если вы хотите отсортировать существующий список, вы должны использовать метод Sort, который не возвращает список, а скорее работает с текущим списком (это метод void).

Метод сортировки/сравнения

Использование: list.Sort(new PersonComparer());

Вот код сравнения. Он был адаптирован из примера

Ответ 2

Другие ответы кажутся более элегантными, чем это, и они заставляют меня чувствовать себя больше noob, однако, если вы поймете, как это сделать, вы можете сортировать любой список в любом случае, не зная ничего. И нет необходимости писать целый новый класс (хотя запись класса сравнения может быть полезна, если вы сортируете другие похожие списки в других частях вашего кода).

peopleList.Sort((x, y) =>
    {
        int compare = x.FirstName.CompareTo(y.FirstName);
        if (compare != 0)
            return compare;

        compare = x.Rank.CompareTo(y.Rank);
        if (compare != 0)
            return compare;

        return x.LastName.CompareTo(y.LastName);
    });

Ответ 3

Мне нравится ответ LINQ. Если это не вариант, вы всегда можете использовать

(x,y) => 2*string.Compare(x.Name,y.Name) + x.Rank.CompareTo(y.Rank)

чтобы сравнение строк всегда доминировало, если оно не равно 0

Ответ 4

На самом деле вы были действительно близки к синтаксису лямбда-сортировки на месте. Вам просто не хватает того, что лямбды могут быть заключены в их пределах:

peopleList.Sort(new Comparison<Person>((x,y) =>
{
    int result = x.FirstName.CompareTo(y.FirstName);
    return (result != 0) ? result : x.Rank.CompareTo(y.Rank);
}));

Это немного меньше усилий, чем написание собственного IComparer<Person>!