查找由NSDictionary对象组成的NSArray中的最大整数值

时间:2012-10-26 16:54:11

标签: objective-c nsarray nsdictionary max

是否有快速有效的方法可以在int NSArrayNSDictionary对象中查找最大for值?我的意思是,我可以实现[(int, string, string), (int, string, string), (int, string, string)]循环,但我正在寻找一些已经调整到最高速度的API函数,因为它运行的是相当大的数据。

valueForKeyPath

我尝试使用{{1}},但到目前为止这对我没有帮助,因为它适用于“普通”NSArray对象。

3 个答案:

答案 0 :(得分:4)

出于好奇,我对valueForKeyPath:与简单迭代进行了一些比较。在运行OS X 10.8.2的iMac核心i7上,对于10M元素的数组,简单迭代速度大约是其两倍。

这是我制作的测试程序:

#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:更快)。任何通用的库方法几乎肯定会在内部产生这种惩罚......

答案 1 :(得分: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

(参见“键值编码编程指南”中的Collection Operators。)

更新:这绝对不是最快的解决方案,正如Arkku在答案中所示。

答案 2 :(得分: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值。

之后只需对NSMutableArray的默认方法进行排序: 代码:

 [arr_details sortUsingDescriptors:[NSArray arrayWithObject:[[NSSortDescriptor alloc] initWithKey:@"distance" ascending:YES]]]