1

オブジェクトで構成される最大int値をすばやく効率的に見つける方法はありますか? 確かに、サイクルを実装できますが、かなり大量のデータで動作しているため、すでに最大速度に調整されている API 関数を探しています。NSArrayNSDictionaryfor

[(int, string, string), (int, string, string), (int, string, string)]

私は試してみましたvalueForKeyPathが、「通常の」 NSArray オブジェクトで動作するため、これまでのところ本当に役に立ちませんでした。

4

3 に答える 3

4

好奇心から、valueForKeyPath:単純な反復と比較してみました。OS X 10.8.2 を実行している私の iMac コア i7 では、単純な反復は 10M 要素の配列に対して約 2 倍高速です。

私が作成したテストプログラムは次のとおりです。

#import <Foundation/Foundation.h>
#undef NDEBUG
#import <assert.h>
#import <limits.h>
#import <stdio.h>
#import <stdlib.h>

#define ELEMENTS_IN_ARRAY 10000000

NSArray *newArrayWithDictionaryElementCount(int count) {
    NSMutableArray *arr = [[NSMutableArray alloc] initWithCapacity:count];
    for (int i = 0; i < count; ++i) {
        [arr addObject:[NSDictionary dictionaryWithObjectsAndKeys:
                        [NSString stringWithFormat:@"value%d", i], @"string",
                        [NSNumber numberWithInt:rand()], @"int",
                        nil]];
    }
    return arr;
}

int maxIntValueByKeyPathInArray(NSArray *arr) {
    return [(NSNumber *)[arr valueForKeyPath:@"@max.int"] intValue];
}

int maxIntValueByIterationInArray(NSArray *arr) {
    int max = INT_MIN;
    for (NSDictionary *dict in arr) {
        int val = [(NSNumber *)[dict valueForKey:@"int"] intValue];
        if (val > max) {
            max = val;
        }
    }
    return max;
}

NSTimeInterval timeExecutionOf(void(^blockToTime)(void)) {
    NSDate *start = [NSDate date];
    blockToTime();
    return -[start timeIntervalSinceNow];
}

int main (int argc, const char *argv[]) {
    srand(time(NULL));
    @autoreleasepool {
        NSArray *arr = newArrayWithDictionaryElementCount(ELEMENTS_IN_ARRAY);
        assert(maxIntValueByIterationInArray(arr) == maxIntValueByKeyPathInArray(arr));
        (void) printf("Time by key path: %f s\n", timeExecutionOf(^{ maxIntValueByKeyPathInArray(arr); }));
        (void) printf("Time by iteration: %f s\n", timeExecutionOf(^{ maxIntValueByIterationInArray(arr); }));
    }
    return 0;
}

私のマシンでの結果:

$ clang -fobjc-arc -framework Foundation -O4 -march=corei7 -o arraytest arraytest.m
$ ./arraytest
Time by key path: 1.809646 s
Time by iteration: 0.886023 s

私の仮説は、反復ソリューションは、これらのデータ構造に対して可能な限り高速であるというものです。配列要素ごとに辞書検索を行う必要はありません。さらに、このカスタムメイドの反復ソリューションには、すべてのNSNumberオブジェクトにint値があることがわかっているという利点があります。比較のために使用isGreaterThan:すると、処理がいくらか遅くなります (ただし、それでも よりは高速ですvalueForKeyPath:)。汎用ライブラリ メソッドは、ほぼ確実にそのペナルティを内部的に被ります…</p>

于 2012-10-26T18:31:58.387 に答える
1

これが高速かどうかはわかりませんが、組み込みの@max演算子をvalueForKeyPath:次のように使用できます。

NSArray *array = @[
    @{ @"value" : @5, @"name" : @"foo"},
    @{ @"value" : @7, @"name" : @"bar"},
    @{ @"value" : @3, @"name" : @"abc"}
];

NSNumber *maximum = [array valueForKeyPath:@"@max.value"];
NSLog(@"%@", maximum);
// Output: 7

この例でvalueは、はディクショナリキーであり、値はNSNumberオブジェクトです。これは、ディクショナリにを格納できないためですint

(「Key-Valueコーディングプログラミングガイド」のコレクション演算子を参照してください。)

更新: Arkkuが彼の答えで示したように、これは間違いなく最速の解決策ではありません。

于 2012-10-26T17:29:15.390 に答える
1

はい、配列をソートするためのより良い方法がありますNSDictionary。与えられたコードのスナッチでは、それは場所の辞書で構成されています。各辞書オブジェクトは、NameキーとDistanceキーで構成されています。

配列は次のようになります。

(   
     {      name = "Electronics Store";
           distance = 9;
     },{      name = "Caffeteria Store";
          distance = 29;
    }    
)

ここでは、辞書の「キー距離」に基づいてソートが行われます。キー距離がint値である必要があることを確認してください。

例えば ​​:

[detail_dict setValue:[NSNumber numberWithInt:[distance intValue]] forKey:@"distance"];

注:距離は並べ替えのint値になります。

その後、デフォルトの方法であるNSMutableArrayCODE: のソートを実行します。

 [arr_details sortUsingDescriptors:[NSArray arrayWithObject:[[NSSortDescriptor alloc] initWithKey:@"distance" ascending:YES]]]
于 2012-10-26T17:29:58.283 に答える