अगर NS NS या NSMutable Shadow में कोई कुंजी है तो कैसे जांचें?


456

मुझे यह जांचने की आवश्यकता है कि क्या किसी तानाशाह के पास चाबी है या नहीं। कैसे?


4
(किसी के लिए भी यहां जाना है। ध्यान दें कि यह एक बहुत पुराना प्रश्न है । सेंटमैकिंटोश का जवाब नीचे दिया गया है, यह कला की स्थिति से पांच साल आगे है। आशा है कि यह मदद करता है।)
फेटी

1
दरअसल, एंडी डेंट का जवाब कला की स्थिति, और अधिक संदर्भ भी देता है। और यह सेंटमैकिंटोश की तुलना में पहले किया था। अपने आप को एक एहसान करो एक स्क्रॉल थोड़ा और नीचे।
पीटर काम्फ

1
वह उपयोग करता है: keysByName [परीक्षण]! = Nil! = Nil check बेमानी है और IMHO कम पठनीय है। मैं सिर्फ TL साझा करना चाहता था; वाक्यविन्यास देख रहे लोगों के लिए DR संस्करण।
एंड्रयू होस

मैं @SaintMacintosh से सहमत हूं। उसका जवाब बहुत अधिक रसीला है।
स्टीव श्वार्क्स

आप अगर जाँच करना चाहते हैं तो NSDictionaryकिसी भी कुंजी (गैर विशिष्ट) शामिल हैं का उपयोग करना चाहिए [dictionary allKeys].count == 0तो countहै 0में कोई भी कुंजी देखते हैं NSDictionary
अलेक्जेंडर अज़ीज़ी

जवाबों:


768

objectForKey यदि कोई कुंजी मौजूद नहीं है, तो nil वापस आएगा।


29
और क्या होगा यदि कुंजी मौजूद है, लेकिन यह संबंधित मूल्य शून्य है?
फ्योडोर सोइकिन

232
यह संभव नहीं है। आप NS NS में nil नहीं जोड़ सकते। आपको [NSNull null]इसके बजाय उपयोग करना होगा ।
ओले बेगमैन

10
@fyodor एक nsdictionay एक NSInvalidArgumentException को फेंक देगा यदि आप एक शून्य मान सम्मिलित करने का प्रयास करते हैं, तो एक ऐसा मामला नहीं होना चाहिए जहां एक कुंजी मौजूद है, लेकिन संबंधित मूल्य शून्य है।
ब्रैड द ऐप गाय

3
क्या आप valueForKey का उपयोग नहीं करना चाहते हैं, क्योंकि यदि आवश्यक हो तो objectForKey कहेंगे?
रफ़ी खाचदौरीयन

6
आप बिल्कुल भी कभी भी JSON शब्दकोष के लिए valueForKey का उपयोग नहीं करना चाहते हैं। ऐसा इसलिए है क्योंकि JSON में कुंजी के रूप में कोई भी स्ट्रिंग हो सकती है । उदाहरण के लिए, यदि इसमें "@count" कुंजी के रूप में है, तो objectForKey: @ "@ count" सही मान देगा, लेकिन valueForKey: @ "@ count" कुंजी / मान जोड़े की संख्या देगा।
gnasher729

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

या

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

100
इस उत्तर में एक उदाहरण धीमा है।
जेम्स वान बॉक्सटेल

5
पढ़ें: इस उत्तर में एक उदाहरण को अवैध माना जाना चाहिए (O (n) के बजाय O (1))
Hertzel Guinness

5
प्रदर्शन बहुत प्रासंगिक है। यह बहुत सही हो सकता है कि यह सटीक रेखा अप्रासंगिक है, लेकिन यदि यह n बार दोहराया जा रहा है, तो अचानक इसके बजाय n समय लेने में n * m लगता है और आप यह पता नहीं लगा सकते हैं कि आपका कार्यक्रम धीमा क्यों है। लगभग सब कुछ एक बार या छोटे मामलों में तेजी से होता है। लेकिन जैसे-जैसे प्रोग्राम गलत डेटा संरचना का उपयोग करते हुए बढ़ते हैं (जैसे पहले उदाहरण में तानाशाह के बजाय सरणी) आपको बड़ी लागत देगा।
एंड्रयू होस

2
कुंजी के अस्तित्व के लिए एक शब्दकोश (या सेट) की जाँच करना O (n) के सबसे खराब मामले के साथ O (1) अपेक्षित है। O नहीं (लॉग (n))। Apple के प्रलेखन स्पष्ट रूप से यह बताते हैं।
एंड्रयू होउस

@JoeBlow "3D मेकिनम डॉट्स को चेतन करें" ऐसा लगता है कि आप कोको टच / ऑब्जेक्टिव-सी को एकता इंजन / सी # के साथ भ्रमित कर रहे हैं। यह सही है कि जिन प्लेटफार्मों पर यह चलता है उन पर एकता इंजन बहुत अक्षम है। हालाँकि, यह बिल्कुल सही नहीं है कि ऑब्जेक्टिव-सी / स्विफ्ट एप्लिकेशन स्वाभाविक रूप से अक्षम हैं, और न ही अधिकांश अनुभवी आईओएस डेवलपर्स सक्रिय रूप से अपने कोड की दक्षता के प्रति जागरूक नहीं हैं। के रूप में "केवल (4 जी) प्रदर्शन प्रोग्रामर के लिए प्रासंगिक" - आप स्पष्ट रूप से एक गेम डेवलपर नहीं कर रहे हैं। 60FPS w / o बैटरी को मारने पर महान ग्राफिक्स और गेमप्ले एक निरंतर चुनौती है।
स्लिप डी। थॉम्पसन

98

उद्देश्य-सी और क्लैंग के हाल के संस्करणों में इसके लिए एक आधुनिक वाक्यविन्यास है:

if (myDictionary[myKey]) {

}

आपको नील के साथ समानता की जांच करने की आवश्यकता नहीं है, क्योंकि केवल गैर-शून्य ऑब्जेक्ट-सी ऑब्जेक्ट को शब्दकोशों (या सरणियों) में संग्रहीत किया जा सकता है। और सभी Objective-C ऑब्जेक्ट्स सत्य मान हैं। यहां तक ​​कि @NO, @0और [NSNull null]सच के रूप में मूल्यांकन करें।

संपादित करें: स्विफ्ट अब एक बात है।

स्विफ्ट के लिए आप कुछ इस तरह की कोशिश करेंगे

if let value = myDictionary[myKey] {

}

यह सिंटैक्स केवल तभी निष्पादित करेगा यदि myKey तानाशाही में है और यदि है तो मान वैरिएबल में संग्रहीत है। ध्यान दें कि यह 0 की तरह भी गलत मूल्यों के लिए काम करता है।


इसके लिए धन्यवाद! मैं बस उत्सुक हूं, लेकिन मैं इस व्यवहार को उद्देश्य-सी वर्ग संदर्भ डेवलपर में प्रलेखित नहीं पा सकता हूं।
ir

2
नहीं आप अंधे नहीं हैं। इस पर जोर नहीं दिया जाता है। लेकिन यहाँ दिखाई दे रहा है ( क्लैंग ) और यहाँ (आधुनिक objc: बहुत नीचे) और यहाँ (संग्रह गाइड: खोज शब्दकोश)
एंड्रयू होओस


9

JSON शब्दकोशों का उपयोग करते समय:

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

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

8

मुझे फ़र्नांडिस का जवाब पसंद है, भले ही आप दो बार ओब्जेक्ट मांगते हैं।

यह भी (कमोबेश मार्टिन ए के समान) करना चाहिए।

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है, objectForKeyतो इसके द्वारा इस्तेमाल की गई हैश तुलना के बजाय एक आईडी तुलना का उपयोग करता है यह NO a पर वापस आ जाएगा 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

हाँ। इस तरह की त्रुटियां बहुत आम हैं और ऐप क्रैश की ओर ले जाती हैं। इसलिए मैं नीचे के रूप में प्रत्येक परियोजना में एनएसडॉर जोड़ने का उपयोग करता हूं:

//.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

NS मंद में कुंजी के अस्तित्व की जाँच के लिए:

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

1
यह वास्तव में इस मौजूदा जवाब का सिर्फ एक दोहराव है ।
पैंग

3

क्योंकि nil को फाउंडेशन डेटा स्ट्रक्चर्स में संग्रहित नहीं किया जा सकता NSNullहै nil। क्योंकि NSNullएक सिंगलटन ऑब्जेक्ट है जिसे आप यह देखने के लिए देख सकते हैं कि NSNullक्या डायरेक्ट पॉइंटर तुलना का उपयोग करके शब्दकोश में संग्रहीत मूल्य है:

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

1
जब मैंने अपनी कुंजी के लिए ऑब्जेक्ट के रूप में NSMutableArray के साथ इसका उपयोग किया तो काम नहीं किया।
पा १२

4
पृथ्वी पर यह क्यों उठी? यह सिर्फ सादा गलत है। यह जाँच सही साबित होगी कि NSNullकुंजी में एकलांक उदाहरण को शब्दकोष में संग्रहीत किया गया है @"myKey"। यह @"myKey"शब्दकोष में नहीं होने की कुंजी के लिए एक पूरी तरह से अलग बात है - वास्तव में दोनों परस्पर अनन्य हैं।
मार्क अमेरी

चूंकि यह अभी भी पूरी तरह से गलत होने के बावजूद पांच वोट हैं, मैं केवल वही दोहरा सकता हूं जो मार्क कहता है: यह कोड परीक्षण करता है कि क्या शब्दकोश में शून्य मान के साथ एक कुंजी है, जो कि बिल्कुल भी कुंजी से युक्त नहीं है।
gnasher729

यह "पूरी तरह से गलत है, लेकिन दिलचस्प जानकारी की ओर
इशारा

यह उत्तर स्पष्ट करने के लिए संपादित किया गया है कि यह क्या करता है (एक तानाशाह में NSNull के लिए जांच करें) और यह क्या नहीं करता है (एक तानाशाह में मूल्य की जांच करें)
एंड्रयू होओस

2

स्विफ्ट 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

मेरा सुझाव है कि आप अस्थायी चर में लुकअप के परिणाम को स्टोर करें, परीक्षण करें कि क्या अस्थायी चर शून्य है और फिर इसका उपयोग करें। इस तरह आप एक ही वस्तु को दो बार नहीं देखते हैं:

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

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

1

जैसा कि आदिराएल ने objectForKeyप्रमुख अस्तित्व की जांच करने का सुझाव दिया था, लेकिन जब आप अशक्त objectForKeyशब्दकोश में कहते हैं , तो ऐप क्रैश हो जाता है इसलिए मैंने इसे निम्नलिखित तरीके से निर्धारित किया है।

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

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

}


हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.