Как работает сортировка списка C # на основе свойства? - PullRequest
2 голосов
/ 04 ноября 2011

Итак, я делаю задание для своего класса C # и у меня есть список объектов. Эти объекты имеют поле int rand, которому присваивается случайное число. Затем я захотел пересортировать объекты в списке на основе этого ранда.

Я нашел эту статью: http://www.developerfusion.com/code/5513/sorting-and-searching-using-c-lists/

И это помогло. Я изменил эту строку, чтобы соответствовать моему коду:

people.Sort(delegate(Person p1, Person p2) { return p1.age.CompareTo(p2.age); });

И он делает то, что я хочу.

То, что я хочу знать: как это работает? Это выглядит очень смущающим для меня.

Ответы [ 6 ]

2 голосов
/ 04 ноября 2011

Если вы используете лямбда-нотацию, с ней становится немного легче читать IMO:

people.Sort((p1, p2) => p1.age.CompareTo(p2.age));

Когда вы используете метод сортировки, вы сортируете список, но метод должен знать, по какой сортировкеи здесь делегирование становится удобным, так как вы можете использовать метод sort, чтобы указать любую сортировку, какую захотите.Вы смотрите на человека 1 и человека 2 и упорядочиваете по возрасту.Если вы хотите отсортировать что-то еще, например, имя (если у вас есть свойство имени), вы бы написали это как:

people.Sort((p1, p2) => string.Compare(p1.Name, p2.Name));
2 голосов
/ 04 ноября 2011

Фактически, метод сортировки должен сортировать на основе некоторого сравнения, в своем текущем коде вы передали сравнение как делегат, вы также можете встроить его в определение класса, чтобы уменьшить сложность кода. Фактически ему просто нужно реализовать IComparable для вашего Personкласс:

 public class Person : IComparable
    {
        public int age { get; set; }

        public int CompareTo(object obj)
        {
            var person = obj as Person;
            if (person != null)
            {
                if (age > person.age)
                    return 1;
                else if (age == person.age)
                    return 0;
                return -1;
            }
            return 1;
        }
    }

, затем просто используйте сортировку без делегатов.

1 голос
/ 04 ноября 2011

список будет использовать переданную функцию (часть return p1.age.CompareTo(p2.age);) для сравнения различных объектов в списке. Это в основном позволяет вам «научить» список тому, как вы хотите сравнивать предметы.

Список будет вызывать вашу функцию, передавая 2 экземпляра класса, который нужно сравнить. вы возвращаете -1, чтобы сказать, что 1-й меньше, чем 2-й, 0, чтобы сказать, что они равны, и 1, чтобы сказать, что 2-й больше. Ваш пример просто передает вызов встроенному сравнению (которое возвращает тот же шаблон -1, 0, 1) для любого типа переменной возраста, скорее всего, целое число.

0 голосов
/ 04 ноября 2011

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

Метод сортировки:

Этот принимает делегата, который содержит «как» сравнить два элемента списка. Как только вы научите список сравнивать с элементами, он сможет отсортировать все элементы, сравнивая их попарно.

Действующий делегат

Встроенный делегат - это объявление метода, который что-то делает.

 delegate(Person p1, Person p2) { return p1.age.CompareTo(p2.age);

Этот делегат рассказывает, как сравнивать два объекта Person. Вы говорите это компилятору: чтобы сравнить p1 с p2, вы должны сравнить p1.age с p2.age .

Объединение вещей

Следующая строка кода содержит оба элемента, метод сортировки и способ сравнения двух объектов People.

people.Sort(delegate(Person p1, Person p2) { return p1.age.CompareTo(p2.age); });

Так что теперь он знает, как отсортировать список.

0 голосов
/ 04 ноября 2011

List.Sort использует алгоритм быстрой сортировки для сортировки списка.В худшем случае сложность составляет O(n ^ 2).Это означает, что в худшем случае предоставленный вами делегат будет вызываться n ^ 2 раз, где n - количество элементов в списке. Делегат подобен указателю на функцию.

Он передает два объекта, которые он хочет сравнить, и предоставленный вами делегат вернет значения -1, 0 или 1.Если его -1, это означает, что p1 меньше, чем p2, если 0 означает, что оба объекта одинаковы, если 1 означает, что p1 больше, чем p2.Итак, в конце концов, предоставленный вами делегат и возвращаемые им значения будут определять, будут ли в списке объекты в descending или ascending порядке.

0 голосов
/ 04 ноября 2011

Чтобы выполнить сортировку, вам необходимо выяснить, идет ли один предмет до или после другой вещи. Имеет смысл, что этот «компаратор» будет функцией или методом, поскольку он разделяет знания.

Если вы посмотрите на документацию для CompareTo, вы заметите, что она должна возвращать -1 (B идет перед A), 0, (A и B равны) или 1 (B идет после A).

Ключевое слово delegate в этом случае создает анонимную функцию, которая используется в качестве компаратора, а тело этой функции вызывает CompareTo, чтобы сравнить свойство возраста двух вовлеченных людей и вернуть результат.

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

...