NSMutableArray Сортировка с помощью селектора - PullRequest
4 голосов
/ 03 марта 2011

Я гуглил, искал stackoverflow без удовлетворительных ответов.

В документации говорится, что:

sortUsingSelector: сортирует массив элементы в порядке возрастания, как определяется методом сравнения указанный данным селектором.

  • (аннулируются) sortUsingSelector: (SEL) компаратор Компаратор параметров Селектор, который указывает метод сравнения для использования сравнить элементы в массиве. сообщение компаратора отправляется каждому объект в массиве и имеет в качестве его один аргумент другой объект в массив. Метод сравнения должен вернуть NSOrderedAscending, если массив меньше аргумента, NSOrderedDescending, если массив больше, чем аргумент, и NSOrderedSame, если они равны.

Я пытаюсь понять, как это действительно работает. Так что, если у меня есть этот метод в моем объекте в класс массива:

- (NSComparisonResult) compareNames: (id) element
{
    return [userName compare: [element userName]];
}

И выполнить его с

[myArray sortUsingSelector:@selector(compareNames:);

Это работает. Проблема в том, что я не знаю, почему это работает. Тип возврата для NSComparisonResult либо По возрастанию, То же, либо По убыванию. Из того, что я получаю, читая документацию метод compareNames отправляется каждому объекту в myArray и сравнивает выбранный свойство объекта (в данном случае это userName) с именем пользователя в другом объекте внутри тот же массив. (Подобно тому, как массив [0] сравнивается с массивом [1]). Я хочу знать, как это Весь процесс идет.

Обновление 1: алгоритм сортировки для нескольких ключей

Я пропустил! в сравнении. Должно быть так:

NSComparisonResult res;
res = [[self userName] compare: [element userName]];
if(res == NSOrderedSame) res = [[self email] compare: [element email]];
return res;

Что касается сортировки по убыванию, вы можете использовать switch или if, чтобы вернуть значение NSComparisonResult, заменив «return res» следующим:

switch (res)
    {
        case NSOrderedAscending:
            return NSOrderedDescending;
            break;
        case NSOrderedDescending :
            return NSOrderedAscending;
            break;
        default:
            return NSOrderedSame;
            break;
    }*/

Ответы [ 2 ]

4 голосов
/ 03 марта 2011

Чтобы ответить на ваши подвопросы в комментариях:

Всегда ли сортировка должна выполняться по возрастанию?- NSOrderedAscending & NSOrderedDescending здесь просто символичны, вы можете подумать о них как об «объекте перед аргументом» и «объекте после аргумента» в порядке сортировки .Например, если вы храните массив NSNumber, то «1 compareTo: 2» должен вернуть NSOrderedAscending, если вы хотите отсортировать по возрастанию значения, и NSOrderedDescending, если вы хотите отсортировать по убыванию значения.

Как вы сортируете с несколькими ключами?- Любой алгоритм сортировки должен знать только, находится ли один элемент до, после или в той же позиции, что и другой. Как вы определяете, что решать вам.Чтобы использовать два ключа сортировки, в псевдокоде используется следующий алгоритм:

To compare item1 and item2
    order = [item1.key1 compareTo:item2.key1];
    if (order == NSOrderedSame) order = [item1.key2 compareTo:item2.key2];
    return order

Расширение до нескольких ключей или более сложных сравнений по мере необходимости.


Последующие комментарии:

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

В английском языке сортировка поДва ключа выполняются следующим образом: сначала сравнивают первый ключ каждого объекта, если они сравниваются не равные, затем возвращают их порядок.Если они сравниваются равными, то продолжайте и сравнивайте второй ключ каждого объекта и возвращайте их порядок.

Это именно то, что делает приведенный выше псевдокод.

Объединение нескольких клавиш проблематично для числаиз причин:

  1. Вы должны объединить их, используя разделитель, который не может быть в ключах.В качестве простого примера рассмотрим сортировку по заданному имени, фамилии, когда у вас есть два человека «Джек Йоландер» и «Джеки Оландер» - наивное объединение производит «Джеколандер» для обоих, и они будут сортироваться одинаково.Таким образом, вам нужен разделитель, который не может встречаться ни в одной из клавиш.

  2. Если ключи разных типов, например, строка и число, вы в конечном итогепреобразование их всех в строки для объединения - расточительно и, возможно, даже неточно.

  3. Простое объединение их расточительно - вы создаете объекты, которые вам не нужныне нужно.

и т. д.Просто сравнивайте ключи в парах, пока не найдете два отличающихся или попадаете в последнюю пару.Работает с любым количеством ключей любых типов и не расточает.

1 голос
/ 03 марта 2011

sortUsingSelector будет использовать быструю сортировку или подобный алгоритм сортировки для сортировки массива.Алгоритмы сортировки должны иметь возможность сравнивать два элемента в коллекции для сортировки и определять, где они должны появляться относительно друг друга в отсортированном порядке.Должен ли А появляться перед В, после В или сразу рядом с ним?Ваш пользовательский метод сортировки (compareNames в вашем примере) - это все, что нужно алгоритму сортировки, чтобы определить это упорядочение.

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

Вы не найдете много онлайн об этом, если будете искать, например, "sortUsingSelector".Это не проблема Objective-C, почти все языки программирования имеют процедуры сортировки, которые используют пользовательскую функцию сравнения для выполнения сортировки.

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