2012-06-11 2 views
0

목표 :가있는 NSArray 우아한 코드를 이용하여 주어진 NSDictionary와 (S)에 대한 고유 키를 포함 수득NSArray 내에서 고유 한 NSDictionary 키를 찾는보다 우아한 방법이 있습니까?

현재 작업 용액과

예 번호 :

NSArray *data = [[NSArray alloc] initWithObjects: 
       [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:1], @"a", [NSNumber numberWithInt:2], @"b", nil], 
       [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:3], @"b", [NSNumber numberWithInt:4], @"c", nil], 
       [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:5], @"a", [NSNumber numberWithInt:6], @"c", nil], 
       [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:7], @"b", [NSNumber numberWithInt:8], @"a", nil], 
       [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:8], @"c", [NSNumber numberWithInt:9], @"b", nil], 
       nil]; 

// create an NSArray of all the dictionary keys within the NSArray *data 
NSMutableSet *setKeys = [[NSMutableSet alloc] init]; 
for (int i=0; i<[data count]; i++) { 
    [setKeys addObjectsFromArray:[[data objectAtIndex:i] allKeys]]; 
} 
NSArray *arrayKeys = [setKeys allObjects]; 
NSLog(@"arrayKeys: %@", arrayKeys); 

키의 원하는 어레이를 리턴

2012-06-11 16:52:57.351 test.kvc[6497:403] arrayKeys: (
    a, 
    b, 
    c 
) 

질문 : 더 우아한 방법이 있나요 접근하고 있니? 확실히 배열을 통해 반복하지 않고도 모든 키를 얻을 수있는 KVC 접근 방식이 있어야합니까? 저는 Apple Developer Documentation을보고 있었고 해결책을 찾을 수 없습니다. 어떤 아이디어? (순수한 성능보다는 코드의 우아함).

NSMutableSet *setKeys = [[NSMutableSet alloc] init]; 
for (NSDictionary* dict in data) { 
    for (id key in [dict keyEnumerator]) { 
     [setKeys addObject:key]; 
    } 
} 

을하지만 특히 일반적인 작업을 수행하지 않는, 그래서 몇 가지 매우 우아한 방법을 찾을 기대하지 않을 것이다 :

답변

8

보통 이런 식으로 뭔가를 수행하여 KVC를 사용할 수 있습니다 : 당신이 블록을 원하는 경우

NSMutableSet *setKeys = [[NSMutableSet alloc] init]; 

for(NSDictionary *dict in data) { 
    [setKeys addObjectsFromArray:[dict allKeys]]; 
} 

NSArray *arrayKeys = [setKeys allObjects]; 

당신이 사용할 수 그러나 NSDictionary은에 의해 사용되는 valueForKey: 선택기를 무시합니다. KVC 내부 구조이므로 제대로 작동하지 않습니다. documentation for NSDictionary's valueForKey: method

은 우리에게 그 이야기 :

키로 시작하지 않는 경우는 "@", objectForKey를 호출 :. key가 "@"로 시작하면 "@"을 제거하고 [super valueForKey :]를 나머지 키와 함께 호출합니다.

그래서 우리는 단지 @해서 AllKeys 전에 삽입 :

NSArray *uniqueKeys = [data valueForKeyPath:@"@[email protected]"]; 

그리고 우리는 우리가 원하는 것을 얻을 : 코드에 대한

(lldb) po [data valueForKeyPath:@"@[email protected]"] 
(id) $14 = 0x07bb2fc0 <__NSArrayI 0x7bb2fc0>(
c, 
a, 
b 
) 
+0

Brilliant. 나는 KVC 방법이 있어야한다는 것을 알았지 만 모든 것을 합칠 수는 없었다. 건배!! –

+1

소원 나는 더 많은 시간이 답변을 upvote 수 있습니다! – Sohan

0

이 덜 못생긴, 아마도 소폭 빨리, 나는 가정한다. 그것이 당신이 원하는 것이라면 하스켈을 배우십시오.

+0

감사합니다. 목표 -C는 현재 배우는 언어입니다. 하스켈은 기다려야 할 것입니다.) 내 철학은 여러분이 사용하는 언어에 관계없이 항상 우아하고 노력해야한다는 것입니다. –

0

이 작업을 시도 할 수 :

NSArray *uniqueKeys = [data valueForKeyPath:@"@distinctUnionOfArrays.allKeys"; 

:

[data enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { 
    [setKeys addObjectsFromArray:[obj allKeys]]; 
}]; 
+0

감사합니다. 좋아, 좋아. 개인적으로, 나는 non-block 옵션을 더 좋아한다. 우아하고 읽기 쉽습니다. –