【问题标题】:Is there a more elegant way of finding unique NSDictionary keys within an NSArray?有没有更优雅的方法在 NSArray 中查找唯一的 NSDictionary 键?
【发布时间】:2012-06-11 07:02:45
【问题描述】:

目标:使用优雅的代码获取包含给定 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 Developer Documentation,但找不到解决方案。有任何想法吗? (着眼于纯粹的代码优雅而不是性能)。

【问题讨论】:

    标签: objective-c nsarray nsdictionary kvc


    【解决方案1】:

    通常您可以通过执行以下操作来使用 KVC:

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

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

    documentation for NSDictionary's valueForKey: method 告诉我们:

    如果 key 不以“@”开头,则调用 objectForKey:。如果键确实以“@”开头,则去掉“@”并使用键的其余部分调用 [super valueForKey:]。

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

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

    我们得到了我们想要的:

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

    【讨论】:

    • 太棒了。我知道必须有一种 KVC 方式——但我无法将它们全部放在一起。干杯!!
    【解决方案2】:

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

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

    但是你没有做一个特别常见的操作,所以我不希望找到一些非常优雅的方法。如果这就是你想要的,去学习 Haskell。

    【讨论】:

    • 感谢您的代码。 Objective-C 是我目前要学习的语言 - 所以 Haskell 将不得不等待 ;) 我的理念是,无论你使用什么语言,你都应该尝试保持优雅。
    【解决方案3】:

    你可以试试这个:

    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]];
    }];
    

    【讨论】:

    • 谢谢。不错,我喜欢就个人而言,我更喜欢非阻塞选项。优雅易读。
    猜你喜欢
    • 2012-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-04
    • 1970-01-01
    相关资源
    最近更新 更多