有没有一种更优雅的方法在 NSArray 中查找唯一的 NSDictionary 密钥?



目的:使用优雅的代码获取包含给定 NSDictionary 的唯一键的 NSArray

当前工作解决方案的示例代码:

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开发人员文档,但看不到解决方案。 有什么想法吗? (看纯粹的优雅代码而不是性能)。

通常你可以通过做这样的事情来使用KVC:

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

但是NSDictionary会覆盖 KVC 内部使用的valueForKey:选择器,因此这将无法正常工作。

NSDictionary的valueForKey:方法的文档告诉我们:

如果键不以"@"开头,则调用对象为键:。如果键确实以"@"开头,则去除"@"并使用键的其余部分调用[super valueForKey:]。

所以我们只需在 allKeys 之前插入一个@

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

得到了我们想要的:

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

我想这不那么丑陋,而且可能稍微快一点:

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

但是你没有做一个特别常见的操作,所以我不希望找到一些令人难以置信的优雅方法。如果这就是你想要的,那就去学习哈斯克尔吧。

你可以试试这个:

NSMutableSet *setKeys = [[NSMutableSet alloc] init]; 
for(NSDictionary *dict in data) {
    [setKeys addObjectsFromArray:[dict allKeys]];
}
NSArray *arrayKeys = [setKeys allObjects];

如果你更喜欢块,你可以使用它:

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

最新更新