9

NSDictionaryにはobjectForKeyがありますが、キーに対して大文字と小文字が区別されます。のような利用可能な機能はありません

- (id)objectForKey:(id)aKey options:(id) options;

オプションで「NSCaseInsensitiveSearch」を渡すことができます

大文字と小文字を区別しないNSDictionaryからキーを取得するには、以下に記述する次のコードを使用できます。

4

6 に答える 6

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;
}
于 2012-11-28T14:39:15.803 に答える
10

これは、いくつかの理由で含まれていません。

  1. NSDictionaryはハッシュ等式を使用し、ほとんどすべての優れたハッシュアルゴリズムでは、ソース文字列のバリエーションによって異なるハッシュが生成されます。

  2. さらに重要なことに、NSDictionaryキーは文字列ではありません。NSCopyingに準拠するオブジェクトはすべて辞書キーにすることができ、文字列よりもはるかに多くのオブジェクトが含まれます。NSNumberとNSB​​ezierPathの大文字と小文字を区別しない比較はどのようになりますか?

ここでの回答の多くは、辞書を配列に変換して反復処理することになるソリューションを提供します。これは機能します。これが1回限りの場合は、問題ありません。しかし、そのソリューションはちょっと醜く、パフォーマンス特性が悪いです。これが私がたくさん必要としているもの(たとえば、NSDictionaryカテゴリを作成するのに十分なもの)である場合、データ構造レベルで適切に解決したいと思います。

必要なのは、NSDictionaryをラップし、キーの文字列のみを許可し、指定されたキーを自動的に小文字にするクラスです(双方向のマッピングが必要な場合は、元のキーも記憶している可能性があります)。これは実装がかなり簡単で、はるかにクリーンな設計です。一回限りでは重すぎますが、これがあなたがたくさんやっていることなら、きれいにやる価値があると思います。

于 2012-11-28T18:18:54.177 に答える
2

正解は、大文字と小文字を区別するキーを辞書キーとして使用する必要があるということです。 これは、大文字または小文字に変換することと同じではなく、O(1)の平均的な大文字小文字の検索/挿入の複雑さを損なうことはありません。

NSString残念ながら、Cocoaには文字列を大文字と小文字を区別する適切な方法がないようですが、CoreFoundationには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と、現在のシステムロケールが取得されます。これはほとんどの場合問題ありませんが、トルコのユーザーは、「I」が「ı」ではなく「i」と一致することに驚くかもしれません。したがって、を渡すことができます[NSLocale currentLocale]。結果を保存する場合は、ロケール識別子を保存して、そこからロケールを作成することもできます。

したがって、辞書に追加するときは、次のことを行う必要があります。

[dict setObject:obj forKey:foldedString(myKey, locale)];

そしてもう一度見上げる

[dict objectForKey:foldedString(myKey, locale)];

最後に、大文字と小文字を区別して折りたたまれたキーを元の値と一緒に保存することをお勧めします。そうすれば、辞書にアクセスするたびにそれらを折りたたむ必要はありません。

于 2016-09-22T12:35:54.917 に答える
1

以下のコードでは、入力キーの実際のキーを検索します。したがって、input key = @ "naMe"の場合、実際のkey =@"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);
于 2012-11-28T14:26:15.170 に答える
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 ;

     }];
于 2012-11-28T14:47:04.393 に答える
0

NSDictionaryを1か所(おそらく2つまたは3つ)に格納し、そこから取得するだけの場合は、次を使用できます。

[myString lowercaseString]

両者に。辞書オブジェクトがコード全体で使用されている場合は、より厳密な回答が役立ちます。

于 2013-06-05T16:26:02.090 に答える