2013-05-03 2 views
0

내 응용 프로그램에서는 마지막 경로 구성 요소 만 갖는 NSDictionary에 값을 삽입해야합니다. 예 : 내 주어진 사전은NSDictionary의 키 경로

a = 1; 
b = 2; 
c = 3; 
d =  { 
    e = 4; 
    f = 5; 
    g =   { 
     h = 6; 
    }; 
}; 
j =  { 
    k = 7; 
}; 

이며, k의 값을 변경해야합니다. 경로 구성 요소는 @[@"j", @"k"]이어야합니다. 그것은 잘못된 방법,

- (void)recurse:(NSDictionary*)dict keyToFound:(NSString*)ktf stack:(NSMutableArray*)stack parent:(NSString*)parent 
{ 
    for (NSString *key in [dict allKeys]) { 
    if ([key isEqualToString:ktf]) { 
     [stack insertObject:key atIndex:[stack count]]; 

     return; 
    } 
    else { 
     if ([[dict valueForKey:key] isKindOfClass:[NSDictionary class]]) { 
      NSDictionary *d = [dict valueForKey:key]; 
      [stack insertObject:key atIndex:[stack count]]; 
      [self recurse:d keyToFound:ktf stack:stack parent:key]; 
      //[stack removeObject:key]; 
     } 
    } 
} 

}

하지만, obviuos : 나는 그런 뭔가를 시도했다.

+0

왜 첫 번째 포인터를 수정하지 않으면 배열에 이중 포인터가 필요하다고 생각합니까? – CodaFi

+0

@CodaFi 결코 신경 쓰지 마라, 그것은 단지 펜의 미끄럼이다. 당분간 저는이 재귀와 혼동합니다. – Akki

+0

그래서 질문은 당신이 @ "j", @ "k"경로를 찾으려고한다는 것을 의미합니다. 그리고 당신의 코드는 실제로 당신이 @ "k", @ "j"를 얻는다는 것을 의미합니까? 당신이 무엇을 요구하고 있는지 분명하지 않습니다. – Wain

답변

1

여기에 중첩 된 사전의 값을 설정하는 두 가지 간단한 방법입니다. 첫 번째는 키가 존재하고 C 식별자가 될 수 있음을 알고 있다고 가정합니다. 이 경우 setValue:forKeyPath:을 사용하는 것이 가장 좋은 방법입니다. 그렇지 않으면 함수의 간단한 루프 (또는 NSDictionary의 메서드 또는 범주)가 트릭을 수행합니다.

void setValueForPathComponentsOfDictionary(id value, NSArray *components, NSMutableDictionary *dict) { 

    NSMutableArray *parts = [components mutableCopy]; 
    id lastPart = parts.lastObject; 
    [parts removeLastObject]; 

    for (id part in parts) { 
     if (![dict respondsToSelector:@selector(objectForKey:)]) 
      return; // Silently fail. 
     dict = [dict objectForKey:part]; 
    } 

    if ([dict respondsToSelector:@selector(objectForKey:)]) 
     [dict setValue:value forKey:lastPart]; 
} 

int main (int argc, const char * argv[]) 
{ 
    @autoreleasepool { 

     NSMutableDictionary *dict = [@{ 
      @"a":[@{@"a":@1,@"b":@2} mutableCopy], 
      @"b":[@{@"a":@3,@"b":@4} mutableCopy] 
     } mutableCopy]; 

     NSLog(@"Initial Dictionary: %@", dict); 

     [dict setValue:@9 forKeyPath:@"a.b"]; 
     NSLog(@"After setValue:forKeyPath: %@", dict); 

     setValueForPathComponentsOfDictionary(@0, @[@"b",@"a"], dict); 
     NSLog(@"After setValueForPathComponentsOfDictionary %@", dict); 
    } 
    return 0; 
} 
+0

와우! 매우 선명하고 우아한 솔루션. 감사. – Akki

0

좋아, 해결책을 찾았습니다.

- (BOOL)recurse:(NSDictionary*)dict keyToFound:(NSString*)ktf stack:(NSMutableArray*)stack parent:(NSString*)parent 
{ 
    BOOL result = NO; 
    for (NSString *key in [dict allKeys]) { 
     if ([key isEqualToString:ktf]) { 
      [stack insertObject:key atIndex:[stack count]]; 
      return YES; 
     } 
     else { 
      if ([[dict valueForKey:key] isKindOfClass:[NSDictionary class]]) { 
       NSDictionary *d = [dict valueForKey:key]; 
       [stack insertObject:key atIndex:[stack count]]; 
       result = [self recurse:d keyToFound:ktf stack:stack parent:key]; 
       if (!result) { 
        [stack removeLastObject]; 
       } 
      } 
     } 
    } 
    return result; 
} 
0
NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithObjectsAndKeys:@1,@"a", 
         @1,@"b", 
         @2,@"c", 
         [NSMutableDictionary dictionaryWithObjectsAndKeys:@4, @"e", 
         @5, @"f", 
         [NSMutableDictionary dictionaryWithObject:@6 forKey:@"h"], @"g", nil],@"d", 
         [NSMutableDictionary dictionaryWithObject:@7 forKey:@"k"],@"i",nil]; 
NSLog(@"Before %@",dict); 

NSString *keyToChange = @"e"; 
NSString *valueToChange = @"Your New Value"; 

[dict enumerateKeysAndObjectsUsingBlock:^(id key ,id obj, BOOL *stop){ 
    if([key isEqualToString:keyToChange]) 
    { 
     NSLog(@"Found : %@",keyToChange); 
     if(![obj isKindOfClass:[NSArray class]] || ![obj isKindOfClass:[NSDictionary class]] || ![obj isKindOfClass:[NSMutableDictionary class]]) 
     { 
      [dict setValue:@"newval" forKey:keyToChange]; 
      return; 
     } 
    } 
    if([obj isKindOfClass:[NSDictionary class]]) 
    { 
     [obj enumerateKeysAndObjectsUsingBlock:^(id key ,id obj1, BOOL *stop){ 
      if([key isEqualToString:keyToChange]) 
      { 
       if(![obj isKindOfClass:[NSArray class]] || ![obj isKindOfClass:[NSDictionary class]] || ![obj isKindOfClass:[NSMutableDictionary class]]) 
       { 
        NSLog(@"Found : %@",keyToChange); 
        [obj setValue:@"newval" forKey:keyToChange]; 
        return; 
       } 
      } 
     }]; 
    } 
}]; 
NSLog(@"After %@",dict);