Как сделать естественный вид на NSArray?
У меня есть массив объектов, и они мне нужны, отсортированные по их "заголовку". В настоящее время он работает, хотя он использует сортировку ASCII вместо естественной сортировки. Заголовки являются именами файлов, поэтому они выглядят следующим образом:
file1
file2
file3
...
file10
file11
file12
Я получаю, как и следовало ожидать:
file1
file10
file11
file12
file2
file3
...
Кто-нибудь знает, есть ли способ, встроенный в функцию сортировки NSArray, чтобы получить эту естественную сортировку, а не в алфавитном порядке? Я нашел некоторые общие алгоритмы, но я надеялся на что-то встроенное...
Ответы
Ответ 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]];