[英]NSDictionary case insensitive objectForKey:
NSDictionary有objectForKey,但它是密鑰的大小寫。 沒有可用的功能
- (id)objectForKey:(id)aKey options:(id) options;
您可以在選項中傳遞“NSCaseInsensitiveSearch”
要從NSDictionary獲取密鑰,這是一個案例中的一個,可以使用下面編寫的代碼。
您需要使用此功能添加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;
}
由於以下幾個原因,不包括此內容:
NSDictionary使用哈希等式,對於幾乎任何好的哈希算法,源字符串中的任何變化都會產生不同的哈希值。
更重要的是, NSDictionary鍵不是字符串 。 符合NSCopying的任何對象都可以是字典鍵,並且包含的字符串多於字符串。 NSNumber與NSBezierPath的不區分大小寫的比較是什么樣的?
這里的許多答案提供的解決方案相當於將字典轉換為數組並迭代它。 這是有效的,如果你只需要一次性,這很好。 但是這種解決方案有點難看並且具有糟糕的性能特征。 如果這是我需要的東西(比如足以創建一個NSDictionary類別),我想在數據結構級別正確地解決它。
你想要的是一個包裝NSDictionary的類,它只允許鍵的字符串,並在給出鍵時自動降低鍵(如果你需要雙向映射,也可能還記住原始鍵)。 這實現起來相當簡單,設計更加簡潔。 這對於一次性來說太沉重了,但是如果這是你做了很多事情,我認為值得干凈利落。
在下面編寫的代碼中,我搜索輸入鍵的實際鍵。 因此,如果輸入鍵= @“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);
正確的答案是你應該使用大小寫折疊的鍵作為字典鍵。 這與將它們轉換為大寫或小寫不同,並且它不會破壞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)];
最后一個觀察結果是,您可能希望將案例折疊的密鑰與原始值一起存儲,然后您不必在每次訪問字典時折疊它們。
許多答案都是正確的,但這里有一個更多的例子:
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 ;
}];
如果您只在一個地方(可能是兩個或三個)存儲和檢索NSDictionary,您可以使用
[myString lowercaseString]
同時。 如果在您的代碼中使用字典對象,則更嚴格的答案非常有用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.