Сортировка по двум критериям: строка по возрастанию, по возрастанию - PullRequest
13 голосов
/ 04 марта 2010

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

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

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

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

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

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

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)));

Спасибо

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

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

Будет ли точно такой же список, только что отсортированный правильно, правильно?

Ответы [ 4 ]

20 голосов
/ 04 марта 2010

Подход LINQ

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

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

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

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

РЕДАКТИРОВАТЬ: использование ToList() возвращает новый список. Если вы хотите отсортировать существующий список, вам следует использовать метод Sort, который не возвращает список, а работает с текущим списком (это метод void).

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

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

Вот код сравнения. Он был адаптирован на примере MSDN , поэтому я рекомендую прочитать комментарии, которые они использовали, чтобы понять, почему он так структурирован.

public class PersonComparer : IComparer<Person>
{
    public int Compare(Person x, Person y)
    {
        if (x == null)
        {
            if (y == null)
            {
                return 0;
            }
            else
            {
                return -1;
            }
        }
        else
        {
            if (y == null)
            {
                return 1;
            }
            else
            {
                int retval = x.FirstName.CompareTo(y.FirstName);

                if (retval != 0)
                {
                    return retval;
                }
                else
                {
                    return x.Rank.CompareTo(y.Rank);
                }
            }
        }
    }
}
6 голосов
/ 04 марта 2010

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

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);
    });
4 голосов
/ 04 марта 2010

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

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>!

3 голосов
/ 04 марта 2010

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

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

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

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