Каков наиболее эффективный способ сортировки NSSet?

Каков наиболее эффективный способ сортировки объектов в NSSet/NSMutableSet на основе свойства объектов в наборе? Прямо сейчас, как я делаю это, итерации через каждый объект, добавьте их в NSMutableArray и отсортируйте этот массив с помощью NSSortDescriptor.

Ответ 1

попробуйте использовать

[[mySet allObjects] sortedArrayUsingDescriptors:descriptors];

Изменить. Для iOS ≥ 4.0 и Mac OS X ≥ 10.6 вы можете напрямую использовать

[mySet sortedArrayUsingDescriptors:descriptors];

Ответ 2

"Самый эффективный способ" сортировки набора объектов зависит от того, что вы на самом деле имеете в виду. Случайное предположение (которое были сделаны предыдущими ответами) является одноразовым видом объектов в наборе. В этом случае я бы сказал, что это в значительной степени зависит от того, что предлагает @cobbal и что вы придумали - возможно, что-то вроде следующего:

NSMutableArray* array = [NSMutableArray arrayWithCapacity:[set count]];
for (id anObject in set)
    [array addObject:anObject];
[array sortUsingDescriptors:descriptors];

(я говорю, что это подбрасывание, потому что подход @cobbal создает два автореализованных массива, поэтому объем памяти удваивается. Это несущественно для небольших наборов объектов, но технически ни один из них не очень эффективен.)

Однако, если вы сортируете элементы в наборе более одного раза (и особенно если это обычная вещь), это определенно неэффективный подход. Вы можете поддерживать NSMutableArray и синхронизировать его с NSSet, а затем вызывать -sortUsingDescriptors: каждый раз, но даже если массив уже отсортирован, он все равно потребует N сравнений.

Cocoa сам по себе просто не обеспечивает эффективный подход для сохранения коллекции в отсортированном порядке. Java имеет класс TreeSet, который сохраняет элементы в отсортированном порядке всякий раз, когда объект вставлен или удален, но Cocoa нет. Именно эта проблема побудила меня разработать нечто подобное для моего собственного использования.

Как часть структуры структур данных, которую я унаследовал и обновил, я создал протокол и несколько реализаций для отсортированных наборов. Любой из конкретных подклассов будет поддерживать набор различных объектов в отсортированном порядке. Есть еще уточнения, которые должны быть сделаны: главное, что он сортируется на основе результата -compare: (который должен реализовать каждый объект в наборе) и еще не принимает NSSortDescriptor. (Обходной путь - реализовать -compare: сравнить интересующее свойство объектов.)

Один из возможных недостатков заключается в том, что эти классы (в настоящее время) не являются подклассами NS (Mutable) Set, поэтому, если вы должны передать NSSet, он не будет упорядочен. (У протокола есть метод -set, который возвращает NSSet, который, конечно, неупорядочен.) Я планирую исправить это в ближайшее время, как это было сделано с подклассами NSMutableDictionary в рамках. Обратная связь, безусловно, приветствуется.: -)

Ответ 3

Для iOS ≥ 5.0 и Mac OS X ≥ 10.7 вы можете напрямую использовать NSOrderedSet

Ответ 4

NSSet - это набор неупорядоченных объектов. Глядя на ссылки на яблоки Массивы - это упорядоченные коллекции.

Глядя на NSArray, мы обсуждаем примеры сортировки на http://developer.apple.com/documentation/ Cocoa/Концептуальные/Коллекции/Статьи/sortingFilteringArrays...

Пример из ссылки:

NSInteger alphabeticSort(id string1, id string2, void *reverse)
{
    if (*(BOOL *)reverse == YES) {
        return [string2 localizedCaseInsensitiveCompare:string1];
    }
    return [string1 localizedCaseInsensitiveCompare:string2];
}

// assuming anArray is array of unsorted strings

NSArray *sortedArray;

// sort using a selector
sortedArray =
    [anArray sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)];

// sort using a function
BOOL reverseSort = NO;
sortedArray =
    [anArray sortedArrayUsingFunction:alphabeticSort context:&reverseSort];

Ответ 5

Вы не можете сортировать NSSet, потому что "sortedArrayUsingFunction:" устанавливает результат как NSArray... И все верхние подсказки работают только с массивом:)

NSArray *myArray = [mySet sortedArrayUsingDescriptors:descriptors];

Работайте идеально, и вам не нужен другой способ:)

Ответ 6

Так как OS X 10.7 и iOS 5.0 есть NSOrderedSet. Вы можете использовать его для хранения объектов в наборе и сохранения их порядка. NSMutableOrderedSet имеет методы сортировки. В некоторых ситуациях это может привести к повышению производительности, поскольку вам не нужно создавать отдельный объект типа NSArray для хранения отсортированных элементов.