Как сделать естественную сортировку на NSArray? - PullRequest
36 голосов
/ 17 мая 2010

У меня есть массив объектов, и мне нужно, чтобы они были отсортированы по их ключу "title". В настоящее время он работает, хотя использует естественную сортировку ASCII. Заголовки являются именами файлов, поэтому они выглядят так:

file1
file2
file3
...
file10
file11
file12

Я получаю, как и следовало ожидать:

file1
file10
file11
file12
file2
file3
...

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

Ответы [ 5 ]

53 голосов
/ 17 мая 2010

NSString с может быть для сравнения с использованием опции NSNumericSearch .

Одна версия:

NSInteger sort(Obj* a, Obj* b, void*) {
    return [[a title] compare:[b title] options:NSNumericSearch];
}

result = [array sortedArrayUsingFunction:&sort context:nil];

Или более обобщенно:

NSInteger sort(id a, id b, void* p) {
    return [[a valueForKey:(NSString*)p] 
            compare:[b valueForKey:(NSString*)p]
            options:NSNumericSearch];
}

result = [array sortedArrayUsingFunction:&sort context:@"title"]

Или используя блоки:

result = [array sortedArrayUsingComparator:^(Obj* a, Obj* b) { 
    return [[a title] compare:[b title] options:NSNumericSearch]; 
}];
24 голосов
/ 17 мая 2010

Те, кто пытается скопировать поведение сортировки Finder в Mac OS X 10.6 и более поздних версиях и iOS 4 и более поздних версиях, могут использовать localizedStandardCompare: как селектор компаратора.

Те, кто преследует ту же цель в более ранних версиях Mac OS X и / или iOS, должны использовать решение, описанное в String Programming Guide .

4 голосов
/ 10 июня 2014

На основе ответа @ PeterHosey, если вы работаете с массивом строковых объектов:

КОРОТКИЙ ОТВЕТ:

NSArray *orderedTitles = [unorderedTitles sortedArrayUsingSelector:@selector(localizedStandardCompare:)];

ПОЛНЫЙ ПРИМЕР:

NSArray *unorderedTitles = @[
    @"file12",
    @"file1",
    @"file10",
    @"file3",
    @"file2",
    @"file11"
];

NSArray *orderedTitles = [unorderedTitles sortedArrayUsingSelector:@selector(localizedStandardCompare:)];
NSLog(@"orderedTitles = %@", orderedTitles);
/*
orderedTitles = (
    file1,
    file2,
    file3,
    file10,
    file11,
    file12
)
*/
0 голосов
/ 27 февраля 2017

Вы также можете выполнить сортировку следующим образом:

NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"title" ascending:YES selector:@selector(localizedStandardCompare:)];
NSArray *sortedItems = [unsortedItems sortedArrayUsingDescriptors:@[sortDescriptor]];
0 голосов
/ 23 октября 2013

Это работает на iOS

NSString *name0 = @"winter";
NSString *name1 = @"summer";
CFComparisonResult result = CFStringCompareWithOptions(
    (CFStringRef) name0,
    (CFStringRef) name1,
    CFRangeMake (0, CFStringGetLength((CFStringRef) name0)),
    kCFCompareCaseInsensitive | kCFCompareLocalized | kCFCompareNumerically
);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...