【问题标题】:Get list of Values for an NSArray of NSDictionary获取 NSDictionary 的 NSArray 的值列表
【发布时间】:2013-08-26 10:55:39
【问题描述】:

我有以下 NSArray :

NSArray myArray = @[@{@300:@"5 min"},
                    @{@900:@"15 min"},
                    @{@1800:@"30 min"},
                    @{@3600:@"1 hour"}];

我想要我的字典的值列表:

@[@"5 min",@"15 min",@"30 min",@"1 hour"]

还有我的字典键列表:

@[@300, @900, @1800, @3600]

最好的方法是什么?我在想谓词,但我不知道如何使用它?

【问题讨论】:

  • 如果键已经是唯一的,那么多个字典的意义何在?一个简单的字典可以很好地保存所有这些信息,您可以使用相关方法检索您的键/值。
  • 有趣的问题,但必须回答的问题是:您尝试过什么?向我们展示您到目前为止所做的工作以及为什么没有按计划进行。
  • +1。有趣的问题。
  • 我确实尝试过任何方法,但我很确定通过迭代 NSArray 并为每个字典填充一个新的 NSArray 是可能的。但我认为有一种更轻松的方法。

标签: objective-c nsarray nsdictionary nspredicate


【解决方案1】:

如果没有一些代码来显示你想如何去做,就很难确定你到底在追求什么,而且这个问题有点混乱。

首先,谓词就是这样 - 一个可以被证明为真或假的陈述。因此,谓词用于逻辑表达式,包括那些在数据库查询中隐式使用的表达式 - 例如 Core Data。

如果我正确阅读了您的问题,那不是您想要的。您想要的是降低数据模型的复杂性,在此过程中删除一些多余的(希望是)信息。字典数组的一种扁平化。

很公平。

我还可以看到与谓词的混淆是如何产生的——它们通常是使用键值编码构造的。众所周知,KVC 是一种非常强大的技术,可以实现您所追求的目标。它只是与逻辑语句没有太大关系。

解决了这个问题后,您可以使用 KVC 做您想做的事,并且无需大惊小怪。它是这样的:

NSArray *values = [myArray valueForKeyPath: @"@unionOfArrays.@allValues"];

NSArray *keys   = [myArray valueForKeyPath: @"@unionOfArrays.@allKeys"];

一个简短的解释可能是为了:

我们想要的结果是

  1. 每个字典的所有值(或键),获取值(或键)数组的数组
  2. 然后我们想将这些数组扁平化为一个数组。

要使用 KVC 从字典中获取所有值(或键),特殊键分别为 @allValues@allKeys

@unionOfArrays 运算符将从后面的表达式中获得的数组合并,即将其展平为您想要的数组。

您为这种编码简单性付出的代价是您必须将 KVC 密钥路径与集合运算符一起使用,这些运算符只是代码中的字符串。因此,您会失去编译器对语法的任何帮助,并且它不会检查您输入的键是否存在于对象中。同样,如果您输入错误或使用了错误的运算符,调试器和错误消息也无济于事。

【讨论】:

  • 非常感谢您如此完整的回复!由于您解释的原因,我不是 KVC 的专家:“您的代码中只有字符串”,因此调试更加困难。但是objective c中很多强大的工具都使用字符串:(
  • 我无法告诉你我有多喜欢这个答案!非常感谢! :)
【解决方案2】:

您可以使用字典属性 allValues 来获取字典的所有值。

在你的情况下试试这个代码

NSArray *myArray = @[@{@300:@"5 min"},
                     @{@900:@"15 min"},
                     @{@1800:@"30 min"},
                     @{@3600:@"1 hour"}];
NSMutableArray *arr = [NSMutableArray array];
for (NSDictionary *dict in myArray) {
    [arr addObject:[[dict allValues] objectAtIndex:0]];
}
NSLog(@"%@",arr);

注意:确保每个字典中只有一个值。 它会返回

[

5 分钟,

15 分钟,

30 分钟,

1 小时

]

【讨论】:

    【解决方案3】:

    @johnyu 的回答在技术上是正确的,但我认为没有任何理由包含二级循环,尤其是在数据结构保持不变的情况下。

    NSArray *myArray = @[@{@300:@"5 min"},
                         @{@900:@"15 min"},
                         @{@1800:@"30 min"},
                         @{@3600:@"1 hour"}];
    
    NSMutableArray *arrayOfValues = [NSMutableArray new];
    NSMutableArray *arrayOfKeys = [NSMutableArray new];
    
    for (NSDictionary *dictionary in myArray) {
        [arrayOfValues addObject:dictionary.allValues[0]];
        [arrayOfKeys addObject:dictionary.allKeys[0]];
    }
    
    NSLog(@"%@",arrayOfKeys);
    NSLog(@"%@",arrayOfValues);
    

    【讨论】:

    • +1。几乎。 :P 你用一个对象创建一个数组,那个对象就是数组。 :) 但事实上, allValues 和 allKeys 方法似乎是更好的方法。应该是 2 个没有在这段代码中显式分配的 NSArray,并且分配值应该像 arrayOfValues = [ditrionary allValues];
    【解决方案4】:

    试试这个:

    NSArray *myArray = @[@{@300:@"5 min"},
                        @{@900:@"15 min"},
                        @{@1800:@"30 min"},
                        @{@3600:@"1 hour"}];
    NSMutableArray *keyArray = [[NSMutableArray alloc] init];
    NSMutableArray *valueArray = [[NSMutableArray alloc] init];
    for (NSDictionary *dictionary in myArray) {
        for (NSString *key in dictionary) {
            [keyArray addObject:key];
            [valueArray addObject:[dictionary objectForKey:key]];
        }
    }
    

    【讨论】:

    • 这是我的第一个想法,但它是老派之王,我有办法用Predicate 做到这一点?
    • 我试过你的解决方案,效果很好。如果我找不到 Predicat 的解决方案,我会将其作为正确的解决方案
    • 感谢您注意到@iOSCoder,我已修复它。
    猜你喜欢
    • 1970-01-01
    • 2011-06-29
    • 1970-01-01
    • 2016-04-13
    • 1970-01-01
    • 2013-08-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多