NSDictionaryまたはNSMutableDictionaryにキーが含まれているかどうかを確認するにはどうすればよいですか?


456

辞書にキーがあるかどうかを確認する必要があります。どうやって?


4
(ここにググる人のためだけです。これは非常に古い質問であることに注意してください。以下のSaintMacintoshの回答は最新技術です。このQAより5年先です。それが役に立てば幸いです。)
Fattie

1
実際、Andy Dentの回答は、最先端の技術とより多くのコンテキストを提供します。そして、これはSaintMacintoshよりも早く行われた。もう少し下にスクロールしてください。
PeterKämpf14年

1
彼は以下を使用します:keysByName [test]!= nil!= nilチェックは冗長であり、IMHOは読みにくくなります。構文を見ている人のためにTL; DRバージョンを共有したかっただけです。
Andrew Hoos 2014

@SaintMacintoshに同意します。彼の答えははるかに簡潔です。
Steve Schwarcz、2015年

あなたがいるかどうかを確認したい場合はNSDictionary、任意のキー(非特異的)が含まれていますが、使用する必要がある[dictionary allKeys].count == 0場合countである0には、キーが存在しませんNSDictionary
Aleksander Azizi 2015年

回答:


768

objectForKey キーが存在しない場合はnilを返します。


29
また、キーは存在するが、対応する値がnilの場合はどうなりますか?
フョードルソイキン

232
それは可能ではありません。NSDictionaryにnilを追加することはできません。[NSNull null]代わりに使用する必要があります。
Ole Begemann

10
@fyodor nsdictionayは、nil値を挿入しようとするとNSInvalidArgumentExceptionをスローします。そのため、キーが存在することはありませんが、対応する値はnilです。
Brad The App Guy

3
valueForKeyを使用したくないのですか。必要に応じてobjectForKeyを呼び出します。
Raffi Khatchadourian、2011

6
JSONディクショナリにvalueForKeyを使用する必要は絶対にありません。これは、JSONが任意の文字列をキーとして含むことができるためです。たとえば、 "@ count"をキーとして含む場合、objectForKey:@ "@ count"は正しい値を提供しますが、valueForKey:@ "@ count"はキーと値のペアの数を提供します。
gnasher729 2014

162
if ([[dictionary allKeys] containsObject:key]) {
    // contains key
}

または

if ([dictionary objectForKey:key]) {
    // contains object
}

100
この回答の例1は遅いです。
James Van Boxtel、2011年

5
読む:この回答の例1は違法と見なされます(O(1)ではなくO(n))
Hertzel Guinness 2013

5
パフォーマンスは非常に重要です。この正確な行が無関係であることは非常に本当かもしれませんが、それがn回繰り返される場合、n時間かかる代わりに突然、n * mを取るので、プログラムが遅い理由を理解できません。ほとんどすべてが1回または小さい場合に高速です。しかし、プログラムが誤ったデータ構造(最初の例のdictの代わりに配列のような)を使用して成長すると、結果的に大きなコストがかかります。
Andrew Hoos 2014年

2
キーの存在について辞書(またはセット)をチェックすると、最悪の場合O(n)のO(1)が予想されます。O(log(n))ではありません。Appleのドキュメントはこれを明確に説明しています。
Andrew Hoos 14

@JoeBlow 「3Dメカニムドットのアニメーション」 Cocoa Touch / Objective-CとUnity Engine / C#を混同しているようです。Unityエンジンは、それが実行されるプラットフォームではひどく非効率的です。ただし、Objective-C / Swiftアプリケーションが本質的に非効率的であることや、熟練したiOS開発者の多くがコードの効率性を積極的に認識していないことは、まったく真実ではありません。「(4人の)パフォーマンスプログラマーにのみ関連」については、あなたは明らかにゲーム開発者ではありません。バッテリーを殺さずに60FPSで素晴らしいグラフィックスとゲームプレイを続けることは、絶え間ない挑戦です。
Slipp D. Thompson 2016

98

Objective-CとClangのより最近のバージョンには、このための最新の構文があります。

if (myDictionary[myKey]) {

}

辞書(または配列)に保存できるObjective-Cオブジェクトはnil以外なので、nilと等しいかどうかを確認する必要はありません。そして、すべてのObjective-Cオブジェクトは真実の値です。でも@NO@0[NSNull null]trueと評価。

編集:スウィフトは今のものです。

Swiftの場合は、次のようなものを試してみてください

if let value = myDictionary[myKey] {

}

この構文は、myKeyがdictにあり、値がvalue変数に格納されている場合にのみifブロックを実行します。これは0のような誤った値でも機能することに注意してください。


これをありがとう!私は好奇心旺盛ですが、objective-cクラスリファレンスdeveloper.apple.com/library/mac/documentation/Cocoa/Reference/に記載されているこの動作を見つけることができません 。
irh

2
いいえ、あなたは盲目ではありません。強調されていません。しかし、ここ(clang)とここ(モダンobjc:最下部)とここ(コレクションガイド:検索辞書)に表示
Andrew Hoos


9

JSON辞書を使用する場合:

#define isNull(value) value == nil || [value isKindOfClass:[NSNull class]]

if( isNull( dict[@"my_key"] ) )
{
    // do stuff
}

8

objを2回要求しても、私はフェルナンデスの答えが好きです。

これも実行する必要があります(多かれ少なかれMartinのAと同じです)。

id obj;

if ((obj=[dict objectForKey:@"blah"])) {
   // use obj
} else {
   // Do something else like creating the obj and add the kv pair to the dict
}

マーティンとこの答えはどちらもiPad2 iOS 5.0.1 9A405で機能します


5

デバッグに少し時間を費やしただけの非常に厄介な落とし穴-オートコンプリートが機能しているdoesContainと思われるものを使用しようとするプロンプトが表示されます。

を除いて、がdoesContain使用するハッシュ比較の代わりにID比較を使用するobjectForKeyため、文字列キーを持つディクショナリがある場合は、にNOを返しますdoesContain

NSMutableDictionary* keysByName = [[NSMutableDictionary alloc] init];
keysByName[@"fred"] = @1;
NSString* test = @"fred";

if ([keysByName objectForKey:test] != nil)
    NSLog(@"\nit works for key lookups");  // OK
else
    NSLog(@"\nsod it");

if (keysByName[test] != nil)
    NSLog(@"\nit works for key lookups using indexed syntax");  // OK
else
    NSLog(@"\nsod it");

if ([keysByName doesContain:@"fred"])
    NSLog(@"\n doesContain works literally");
else
    NSLog(@"\nsod it");  // this one fails because of id comparison used by doesContain

5

Swiftを使用すると、次のようになります。

if myDic[KEY] != nil {
    // key exists
}

5

はい。この種のエラーは非常に一般的であり、アプリのクラッシュにつながります。だから私は以下のように各プロジェクトにNSDictionaryを追加するために使用します:

//.hファイルコード:

@interface NSDictionary (AppDictionary)

- (id)objectForKeyNotNull : (id)key;

@end

//.mファイルのコードは次のとおりです

#import "NSDictionary+WKDictionary.h"

@implementation NSDictionary (WKDictionary)

 - (id)objectForKeyNotNull:(id)key {

    id object = [self objectForKey:key];
    if (object == [NSNull null])
     return nil;

    return object;
 }

@end

コードでは次のように使用できます:

NSStrting *testString = [dict objectForKeyNotNull:@"blah"];

3

NSDictionary内のキーの存在を確認するには:

if([dictionary objectForKey:@"Replace your key here"] != nil)
    NSLog(@"Key Exists");
else
    NSLog(@"Key not Exists");

1
これは実際には、この既存の回答の繰り返しにすぎません。
パン

3

nilはFoundationデータ構造に格納できないためNSNull、を表す場合がありnilます。NSNullはシングルトンオブジェクトであるため、NSNull直接ポインタ比較を使用して、値がディクショナリに格納されているかどうかを確認できます。

if ((NSNull *)[user objectForKey:@"myKey"] == [NSNull null]) { }

1
NSMutableArrayをキーのオブジェクトとして使用した場合、うまくいきませんでした。
pa12

4
なぜこれが賛成投票になったのですか?それはただの間違いです。シングルトンNSNullインスタンスがディクショナリにkeyの値として格納されている場合、このチェックはtrueを返します@"myKey"。これは、キー@"myKey"が辞書にない場合とはまったく異なります。実際、この2つは相互に排他的です。
Mark Amery 2013年

これは完全に間違っているにもかかわらず5票を投じているため、Markの言うことだけを繰り返すことができます。このコードは、辞書にnull値のキーが含まれているかどうかをテストします。
gnasher729 2014

「完全に間違っているが、興味深い情報を指し示している」
Fattie

この回答は、それが何をするか(dictでNSNullをチェックする)と何をしないか(dictで値をチェックする)を明確にするために編集されました
Andrew Hoos

2

Swift 4.2のソリューション

したがって、辞書にキーが含まれているかどうかの質問に答える場合は、次のように質問します。

let keyExists = dict[key] != nil

値が必要で、辞書にキーが含まれていることがわかっている場合は、次のように言います。

let val = dict[key]!

しかし、通常のように、キーが含まれていることがわからない場合-キーをフェッチして使用したいのですが、それが存在する場合のみ-次のようなものを使用しますif let

if let val = dict[key] {
    // now val is not nil and the Optional has been unwrapped, so use it
}

1

ルックアップの結果を一時変数に保存し、一時変数がnilかどうかをテストしてから使用することをお勧めします。そうすれば、同じオブジェクトを2度見上げることはありません。

id obj = [dict objectForKey:@"blah"];

if (obj) {
   // use obj
} else {
   // Do something else
}

1

AdiraelがobjectForKeyキーの存在を確認することを提案したようにobjectForKey、nullable辞書で呼び出すと、アプリがクラッシュするため、次の方法でこれを修正しました。

- (instancetype)initWithDictionary:(NSDictionary*)dictionary {
id object = dictionary;

if (dictionary && (object != [NSNull null])) {
    self.name = [dictionary objectForKey:@"name"];
    self.age = [dictionary objectForKey:@"age"];
}
return self;

}


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.