NSDictionary有objectForKey,但它是密钥的大小写。有 否 功能,如
- (id)objectForKey:(id)aKey options:(id) options;
在选项中你可以传递“NSCaseInsensitiveSearch”
要从NSDictionary获取密钥,这是一个案例非常重要的,可以使用下面编写的代码。
答案 0 :(得分:12)
您需要使用此功能添加NSDictionary类的类别
- (id)objectForCaseInsensitiveKey:(NSString *)key {
NSArray *allKeys = [self allKeys];
for (NSString *str in allKeys) {
if ([key caseInsensitiveCompare:str] == NSOrderedSame) {
return [self objectForKey:str];
}
}
return nil;
}
答案 1 :(得分:9)
由于以下几个原因,不包括此内容:
NSDictionary使用哈希等式,对于几乎任何好的哈希算法,源字符串中的任何变化都会产生不同的哈希值。
更重要的是, NSDictionary键不是字符串。符合NSCopying的任何对象都可以是字典键,并且包含的字符串多于字符串。 NSNumber与NSBezierPath的不区分大小写的比较是什么样的?
这里的许多答案提供的解决方案相当于将字典转换为数组并迭代它。这是有效的,如果你只需要一次性,这很好。但是这种解决方案有点难看并且具有糟糕的性能特征。如果这是我需要的东西(比如足以创建一个NSDictionary类别),我想在数据结构级别正确地解决它。
你想要的是一个包装NSDictionary的类,它只允许键的字符串并在给出键时自动降低键(如果需要双向映射,也可能记住原始键)。这实现起来相当简单,设计更加简洁。这对于一次性而言太沉重了,但如果这是你做的很多事情,我认为值得干净利落。
答案 2 :(得分:1)
在下面的代码中,我搜索输入键的实际键。因此,如果输入键= @“naMe”,则实际键= @“name”。
NSDictionary *dic=[NSDictionary dictionaryWithObjectsAndKeys:@"John",@"Name",@"123456",@"empId", nil];
NSString *key=@"naMe";
NSString *name=[dic objectForKey:key];
if(name==nil){
NSPredicate *searchPred=[NSPredicate predicateWithFormat:@"self LIKE[cd] %@",key];
NSArray *searchedKeys=[[dic allKeys] filteredArrayUsingPredicate:searchPred];
if(searchedKeys.count>0){
name=[dic objectForKey:[searchedKeys objectAtIndex:0]];
}
}
NSLog(@"Name = %@",name);
答案 3 :(得分:1)
正确的答案是你应该使用大小写折叠的键作为字典键。 这与将它们转换为大写或小写不同,它不会破坏O(1)平均案例搜索/插入复杂性。
不幸的是,Cocoa似乎没有合适的NSString
方法来对字符串进行大小写,但Core Foundation有CFStringFold()
可以用于此目的。让我们写一个简短的函数来完成必要的工作:
NSString *foldedString(NSString *s, NSLocale *locale)
{
CFMutableStringRef ret = CFStringCreateMutableCopy(kCFAllocatorDefault, 0,
(__bridge CFStringRef)s);
CFStringNormalize(ret, kCFStringNormalizationFormD);
CFStringFold(ret, kCFCompareCaseInsensitive, (__bridge CFLocaleRef)locale);
return (__bridge_transfer NSString *)ret;
}
注意 locale 参数很重要。如果指定NULL
,您将获得当前系统区域设置。这在大多数情况下会没问题,但土耳其用户可能会对“我”与“我”匹配而不是“ı”感到惊讶。您可能因此希望传递[NSLocale currentLocale]
,如果您要保存结果,可能也希望保存区域设置标识符并从中创建区域设置。
因此,在添加到字典时,您现在需要执行
[dict setObject:obj forKey:foldedString(myKey, locale)];
再次抬头
[dict objectForKey:foldedString(myKey, locale)];
最后一个观察结果是,您可能希望将案例折叠的密钥与原始值一起存储,然后您不必在每次访问字典时都将其折叠。
答案 4 :(得分:0)
许多答案都是正确的,但这里有一个更多的例子:
NSDictionary* dict= @{ @"hello" : @"Hey" };
NSArray* keys= [dict allKeys];
NSUInteger index=[keys indexOfObjectPassingTest: ^BOOL (id obj, NSUInteger index, BOOL* stop)
{
if( [obj caseInsensitiveCompare: @"Hello"]==NSOrderedSame)
{
*stop= YES;
return YES;
}
else
{
return NO;
}
}];
我个人觉得这种方法比较简单,但每个人都有自己的编程风格。
修改强>
不太可读但更短的解决方案:
NSDictionary* dict= @{ @"hello" : @"Hey" };
NSArray* keys= [dict allKeys];
NSUInteger index=[keys indexOfObjectPassingTest: ^BOOL (id obj, NSUInteger index, BOOL* stop)
{
return *stop= [obj caseInsensitiveCompare: @"Hello"]==NSOrderedSame ;
}];
答案 5 :(得分:0)
如果您只在一个地方(可能是两个或三个)存储和检索NSDictionary,您可以使用
[myString lowercaseString]
两者都有。如果在整个代码中使用字典对象,则更严格的答案很有用。