查找NSDictionary密钥的简单方法是什么?

时间:2012-11-13 15:57:54

标签: objective-c arrays performance optimization dictionary

在我正在研究的程序中,我正在使用C数组的字符(它可能是一个非常大的数组,因此我不想使用NSArray)。每个人都存储一个与特定状态相对应的值。

因此,我可以存储有关每个状态的一些信息,我正在使用NSDictionary。每个键对应于可能的状态值。对于每个键,该值是一个子词典,其中包含我需要的与状态值相对应的信息。

目前,每当我想从NSDictionary中提取信息时,我都会执行以下操作:

for(i=0; i<arrayLen; i++) {

NSString *lookupKey1 = [[NSString alloc]initWithFormat:@"%i", array[i]];
int stateInfo1 = [[[statesDict objectForKey:lookupKey1] 
                                objectForKey:@"infoKey1"] intValue];
[lookupKey1 release];


NSString *lookupKey2 = [[NSString alloc]initWithFormat:@"%i", array[i]];
int stateInfo2 = [[[statesDict objectForKey:lookupKey2] 
                                objectForKey:@"infoKey2"] intValue];
[lookupKey2 release];


// Now do something with the values just obtained...

}

这很好用,但是我不喜欢这样做是因为我必须分配一个NSString,只是为了查找一个密钥。感觉就像我正在执行不必要的操作。这是我特别关注的问题,因为我正在迭代一个大型阵列而且我不希望以这种方式减慢速度,除非我绝对必须这样做。

当我试图像我原先希望的那样简单地传递char时:

char stateInfo = [[[statesDict objectForKey:array[i]] 
                                objectForKey:@"infoKey"] charValue];

编译器发出警告&#34;传递objectForKey的参数1:从整数中生成指针而不使用强制转换&#34;并且调试器抛出EXC_BAD_ACCESS异常。

我也试过传入格式化的字符串文字:

char stateInfo = [[[statesDict objectForKey:(@"%i", array[i])] 
                                objectForKey:@"infoKey"] charValue];

这会引发完全相同的错误。有没有人知道是否有更有效的方法来做我想做的事情,或者我在第一个片段中描述的方式是正确的&#39;如何去做我想做的事情?

3 个答案:

答案 0 :(得分:2)

您可以采取两项措施来简化访问:

  • 使用NSNumber代替NSString作为NSDictionary
  • 的键
  • 使用自动释放的密钥来避免调用release

这会简化您的代码:

int stateInfo2 = [[[statesDict objectForKey:[NSNumber numberWithInt:array[i]]] 
                            objectForKey:@"infoKey2"] intValue];

如果代码数量相对较少,很可能在当前实现中不会分配NSNumber:根据this link[NSNumber numberWithInt:...]将返回同一个对象表示整数值较低。

编辑:由于属性列表不支持NSString以外的类型的键,您需要将从plist获取的字典转换为具有NSNumber个键的字典,如下所示:

NSDictionary *fromPlist = ... // This is your original dictionary
NSMutableDictionary *target = [NSMutableDictionary dictionary];
[fromPlist enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop){
    [target setObject:obj forKey:[key intValue]];
}];

答案 1 :(得分:2)

NSDictionary *只能将对象作为键和值。当你传递一个char时,它会将它转换为指针。

@dasblinkenlight提出了一个很好的建议,虽然我猜你在框架决定给你一个共享的NSNumber实例时会有点摆布,这可能因操作系统版本而异。

另一种选择是重命名源文件,使扩展名为.mm并使用c ++ std :: map,它可以处理这类事情。

#import <map>

@implementation MyClass {
  std::map<char, int> statesMap;

...

int stateInfo1 = statesMap[i];

所有人都说,我担心你会对此不必要地担心:

  

所有这些对象都不利于提高性能

即使使用包含10,000个元素的数组,使用唯一对象键的内存开销也将达到约80k。相当于几个图标。除非您制作了数百个,否则不太可能导致内存问题。在性能方面,从分析工具中获取数据,而不是假设。瓶颈不太可能出现在你期望的地方。

答案 2 :(得分:1)

你试过吗

char stateInfo = [[[statesDict objectForKey:[NSString stringWithFormat:@"%i", array[i]] 
                                objectForKey:@"infoKey"] charValue];