web-dev-qa-db-ja.com

NSSortDescriptorを使用してNSIntegerのようにNSString値を並べ替える

サーバーからの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の正しい順序で配置するにはどうすればよいですか?

28
Abhinav

これを行うには、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ドキュメント ここ

44
jonkroll

[list sortUsingSelector:@selector(localizedStandardCompare:)];は、リストを「人間」の方法でソートします(したがって、「1」と「2」の間ではなく、「11」が最後になります)。しかし、本当にこれらの文字列を数字として扱いたい場合は、最初に数字にする必要があります。

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

整数の値に基づいて並べ替えます。

16
lucidbeing

文字列を NSNumericSearch オプションと比較する必要があります。

NSNumericSearch
文字列内の数値は、数値を使用して比較されます。つまり、Name2.txt <Name7.txt <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];
 }];
11
Josh Caswell
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
}];

パフォーマンスについての保証はありません

7
FluffulousChimp

上記のすべてのメソッドを実装するには、基本的な知識が必要です。しかし、初心者には、最も簡単な方法を提案します–ネイティブブロック方式を使用する

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

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

    return aValue > bValue;
}];
0
Subash Varadhan

入力

{
    "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
starfall