Сортировка значений NSString, как будто NSInteger с использованием NSSortDescriptor - PullRequest
28 голосов
/ 13 марта 2012

Я создал дескриптор сортировки для сортировки ответа plist, поступающего с моего сервера. Это хорошо работает с ключом сортировки, имеющим значения до 9. С более чем 10 элементами я вижу резкие результаты с ключом сортировки, расположенным в порядке = 1, 10, 11, 2, 3, 4, 5, 6, 7, 8, 9

NSSortDescriptor *aSortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"sort" ascending:YES];
self.myList = [NSMutableArray arrayWithArray:[unsortedList sortedArrayUsingDescriptors:[NSArray arrayWithObject:aSortDescriptor]]];

Как заставить его расположить в правильном порядке 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11?

Ответы [ 7 ]

44 голосов
/ 13 марта 2012

Вы можете сделать это, внедрив пользовательский блок компаратора при создании NSSortDescriptor:

NSSortDescriptor *aSortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"sort" ascending:YES comparator:^(id obj1, id obj2) {

    if ([obj1 integerValue] > [obj2 integerValue]) {
        return (NSComparisonResult)NSOrderedDescending;
    }
    if ([obj1 integerValue] < [obj2 integerValue]) {
        return (NSComparisonResult)NSOrderedAscending;
    }
    return (NSComparisonResult)NSOrderedSame;
}];
self.myList = [NSMutableArray arrayWithArray:[unsortedList sortedArrayUsingDescriptors:[NSArray arrayWithObject:aSortDescriptor]]];

См. Документацию Apple здесь

39 голосов
/ 13 марта 2012

[list sortUsingSelector:@selector(localizedStandardCompare:)]; отсортирует список «по-человечески» (поэтому «11» будет последним, а не между «1» и «2»). Но если вы действительно хотите относиться к этим строкам как к числам, вы должны сначала сделать их номерами!

16 голосов
/ 26 марта 2013
NSSortDescriptor *aSortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"sort.intValue" ascending:YES];
self.myList = [NSMutableArray arrayWithArray:[unsortedList sortedArrayUsingDescriptors:[NSArray arrayWithObject:aSortDescriptor]]];

Сортировка по значению целого числа.

11 голосов
/ 13 марта 2012

Вам нужно сравнить свои строки с опцией NSNumericSearch:

NSNumericSearch
Числа в строках сравниваются с использованием числового значения, то есть Name2.txt <<code>Name7.txt <<code>Name25.txt.

, который требует, чтобы для сравнения был вызван метод compare:options:.

Чтобы сделать это, ваш дескриптор сортировки может использовать NSComparator Block :

[NSSortDescriptor sortDescriptorWithKey:@"self"
                              ascending:YES
                             comparator:^(NSString * string1, NSString * string2){
                                            return [string1 compare:string2
                                                            options:NSNumericSearch];
 }];

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

[unsortedList sortedArrayUsingComparator:^NSComparisonResult (NSString * string1, NSString * string2){
    return [string1 compare:string2
                    options:NSNumericSearch];
 }];
7 голосов
/ 13 марта 2012
NSMutableArray *list = [NSMutableArray arrayWithObjects:@"11",@"2",@"3",@"1", nil];
[list sortUsingComparator:^NSComparisonResult(id obj1, id obj2) {
    NSInteger firstInteger = [obj1 integerValue];
    NSInteger secondInteger = [obj2 integerValue];
    if( firstInteger > secondInteger) return NSOrderedDescending;
    if( firstInteger == secondInteger) return NSOrderedSame;
    return NSOrderedAscending; // edited
}];

Нет гарантий по производительности

0 голосов
/ 14 октября 2017

ввод

{
    "seats": [{
        "seatNumber": "1"
    }, {
        "seatNumber": "10"
    }, {
        "seatNumber": "2"
    }]
}

сортировка с использованием [NSSortDescriptor sortDescriptorWithKey: @ "seatNumber" ascending: YES селектор: @selector (localizedStandardCompare :)]]. Ключ должен использовать localizedStandardCompare. Это решит вашу проблему.

NSArray *seats = [self.seats sortedArrayUsingDescriptors:@[[NSSortDescriptor sortDescriptorWithKey:@"seatNumber" ascending:YES selector:@selector(localizedStandardCompare:)]]];

выход

{
    "seats": [{
        "seatNumber": "1"
    }, {
        "seatNumber": "2"
    }, {
        "seatNumber": "10"
    }]
}

документация: https://developer.apple.com/documentation/foundation/nsstring/1409742-localizedstandardcompare

0 голосов
/ 26 июля 2016

Все вышеперечисленные методы требуют хороших знаний основ для реализации; но для новичков я предлагаю самый простой способ - использовать нативный метод блока

NSArray* sortedArr =[fetchResults sortedArrayUsingComparator:^NSComparisonResult(id a, id b) {

    int aValue = [[a valueForKey:@"subgroupId"] intValue];
    int bValue = [[b valueForKey:@"subgroupId"] intValue];

    return aValue > bValue;
}];
...