Подтвердить что ты не робот

Как сделать естественный вид на NSArray?

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

file1
file2
file3
...
file10
file11
file12

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

file1
file10
file11
file12
file2
file3
...

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

4b9b3361

Ответ 1

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]; 
}];

Ответ 2

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

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

Ответ 3

На основе ответа @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
)
*/

Ответ 4

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

NSString *name0 = @"winter";
NSString *name1 = @"summer";
CFComparisonResult result = CFStringCompareWithOptions(
    (CFStringRef) name0,
    (CFStringRef) name1,
    CFRangeMake (0, CFStringGetLength((CFStringRef) name0)),
    kCFCompareCaseInsensitive | kCFCompareLocalized | kCFCompareNumerically
);

Ответ 5

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

NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"title" ascending:YES selector:@selector(localizedStandardCompare:)];
NSArray *sortedItems = [unsortedItems sortedArrayUsingDescriptors:@[sortDescriptor]];