2012-02-08 19 views
13

के एनएस डिक्शनरी को रिकर्सिव रूप से पार करता है क्या किसी ने अज्ञात संरचना के एनएस डिक्शनरी के रिकर्सिव ऑर्डर ट्रैवर्सल किया है? मैं किसी भी NSDictionary लेना चाहता हूं और प्रत्येक स्तर को पदानुक्रमित क्रम में संसाधित करना चाहता हूं।अज्ञात संरचना

1) यह डेटा मान्य JSON से आ रहा है। क्या यह कहना सुरक्षित है कि एसबीजेसन (जेएसओएन फ्रेमवर्क) जैसे ढांचे से निर्मित एनएस डिक्शनरी न केवल घोंसला वाले शब्दकोश, सरणी और मनमाने ढंग से पत्ते का संयोजन होगा?

2) तेजी से गणना का उपयोग करके एक सामान्य ट्रैवर्सल कैसे किया जा सकता है जो दोनों सरणी और शब्दकोश दोनों के लिए काम करता है? नीचे दिए गए कोड के साथ, एक बार जब मैं किसी सरणी के भीतर एक शब्दकोश में जाता हूं, तो यह ट्रैवर्सिंग बंद कर देता है। हालांकि, अगर मैं सरणी स्थिति (सरणी के भीतर शब्दकोशों की जांच करने के लिए) में रिकर्सन जारी रखता हूं, तो यह id value = [dict valueForKey:key]; के अगले पुनरावृत्ति पर -[__NSCFDictionary length]: unrecognized selector sent to instance SIGABRT के साथ पुनरावृत्ति जारी रखता है। मुझे नहीं पता कि यह एक समस्या क्यों होगी, क्योंकि मैं पहले से ही उस स्तर को एक शीर्ष-स्तरीय शब्दकोश (जहां उप-स्तरीय शब्दकोशों की सरणी मिली थी) के साथ पिछली बार मिल गई थी।

-(void)processParsedObject:(id)dict counter:(int)i parent:(NSString *)parent 
{ 
    for (id key in dict) { 
     id value = [dict valueForKey:key]; 
     NSLog(@"%i : %@ : %@ -> %@", i, [value class], parent, key); 

     if ([value isKindOfClass:[NSDictionary class]]) 
     { 
      i++; 
      NSDictionary* newDict = (NSDictionary*)value; 
      [self processParsedObject:newDict counter:i parent:(NSString*)key]; 
      i--; 
     } 
     else if ([value isKindOfClass:[NSArray class]]) 
     { 
      for (id obj in value) { 
       NSLog(@"Obj Type: %@", [obj class]); 
      } 
     } 
    } 
} 

बहुत धन्यवाद

+0

आप एनएसएलओजी एनएसएलओजी हर बार ऐसा करते हैं। –

+0

सही, लेकिन सामान्य रूप से बिंदु प्रक्रिया में नेस्टेड ऑब्जेक्ट्स को कैप्चर और संसाधित करना है, न कि उन्हें लॉग इन करें। –

+0

आपको केवल 'isKindOfClass' का उपयोग करने के तरीके सीखने की आवश्यकता है। –

उत्तर

31

मैं कुछ इसी तरह है, जहां मैं एक JSON संरचित वस्तु एक वेब सेवा से आने वाले पार और एक परिवर्तनशील संस्करण में प्रत्येक तत्व में बदल सकते हैं किया है।

- (void)processParsedObject:(id)object 
{ 
    [self processParsedObject:object depth:0 parent:nil]; 
} 

- (void)processParsedObject:(id)object depth:(int)depth parent:(id)parent 
{  
    if ([object isKindOfClass:[NSDictionary class]]) 
    { 
     for (NSString* key in [object allKeys]) 
     { 
      id child = [object objectForKey:key]; 
      [self processParsedObject:child depth:(depth + 1) parent:object]; 
     } 
    } 
    else if ([object isKindOfClass:[NSArray class]]) 
    { 
     for (id child in object) 
     { 
      [self processParsedObject:child depth:(depth + 1) parent:object]; 
     } 
    } 
    else 
    { 
     // This object is not a container you might be interested in it's value 
     NSLog(@"Node: %@ depth: %d", [object description], depth); 
    } 
} 
+0

उत्कृष्ट। मैं इसे एक शॉट दूंगा और वापस रिपोर्ट करूंगा। –

+0

एक आकर्षण की तरह काम करता है! मुझे यह पसंद है कि आपने इसे एक-पैरा विधि के बारे में कैसे बताया, इसलिए कॉलर को अस्पष्ट पैराम जानने की आवश्यकता नहीं है। –

+0

आप 'पैरेंट' क्यों पास करते हैं? ऐसा लगता है कि यह कभी भी इस्तेमाल नहीं किया जाता है। –

4

मैं तो मैं दुबारा लिखा क्या योएल था और इस के साथ आया था मानों के लिए कुंजी नाम पता करने के लिए की जरूरत:

- (void)enumerateJSONToFindKeys:(id)object forKeyNamed:(NSString *)keyName 
{ 
    if ([object isKindOfClass:[NSDictionary class]]) 
    { 
     // If it's a dictionary, enumerate it and pass in each key value to check 
     [object enumerateKeysAndObjectsUsingBlock:^(id key, id value, BOOL *stop) { 
      [self enumerateJSONToFindKeys:value forKeyNamed:key]; 
     }]; 
    } 
    else if ([object isKindOfClass:[NSArray class]]) 
    { 
     // If it's an array, pass in the objects of the array to check 
     [object enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { 
      [self enumerateJSONToFindKeys:obj forKeyNamed:nil]; 
     }]; 
    } 
    else 
    { 
     // If we got here (i.e. it's not a dictionary or array) so its a key/value that we needed 
     NSLog(@"We found key %@ with value %@", keyName, object); 
    } 
} 

और फिर आप इसे कहते चाहते हैं की तरह:

[self enumerateJSONToFindKeys:JSON forKeyNamed:nil]; 

वैकल्पिक रूप से, यदि आप एक दिया गया कुंजी पथ म्यूटेबल बनाना चाहते हैं (तो आप इसे setValue:forKeyPath: का उपयोग करके वापस लिख सकते हैं), आप कुछ कर सकते हैं नीचे की तरह चीज:

- (void)makeDictionariesMutableForKeyPath:(NSString *)keyPath { 
    NSArray *keys = [keyPath componentsSeparatedByString:@"."]; 

    NSString *currentKeyPath = nil; 
    for (NSString *key in keys) { 
     if (currentKeyPath) { 
      NSString *nextKeyPathAddition = [NSString stringWithFormat:@".%@", key]; 
      currentKeyPath = [currentKeyPath stringByAppendingString:nextKeyPathAddition]; 
     } else { 
      currentKeyPath = key; 
     } 

     id value = [self.mutableDictionary valueForKeyPath:currentKeyPath]; 
     if ([value isKindOfClass:NSDictionary.class]) { 
      NSMutableDictionary *mutableCopy = [(NSDictionary *)value mutableCopy]; 
      [self.mutableDictionary setValue:mutableCopy forKeyPath:currentKeyPath]; 
     } 
    } 

} 
+0

हाय, क्या सभी केटपाथ वापस करने का कोई तरीका है? ... सभी उप कुंजी के लिए "keyname.keyname.keyname" जैसी कुछ ?? – Mike97

+0

... ओह ... कीपैथ – Mike97

संबंधित मुद्दे