我有一些不友好的字典数组,这些字典又包含数据数组,我试图根据传递谓词的任何内部数组来过滤外部数组。我似乎无法创建NSPredicate来完成这项工作。我开始时:

NSPredicate *lookupPredicate = [NSPredicate predicateWithFormat:
             @"row_values.property_id == %@ AND row_values.property_value == %@",
               @"47cc67093475061e01000540", @"Male"];

[dataRows filterUsingPredicate:lookupPredicate];

这将不返回任何值。我尝试了各种形式的ANY,但似乎找不到能解析的任何内容。同样,目标是仅保留那些内部数组字典内容的谓词为true的外部数组字典。我可以看到我每天都在想办法解决这个问题,对此...之以鼻...有什么主意吗?
dataRows:
(
 {
    row = 1;
    "row_values" =     (
            {
              "property_id" = 47cc67093475061e01000542;
              "property_value" = "Mr.";
            },
            {
               "property_id" = 47cc67093475061e01000540;
               "property_value" = Male;
            }
     );
 },
 {
    row = 2;
    "row_values" =     (
           {
             "property_id" = 47cc67093475061e01000542;
             "property_value" = "Ms.";
           },
 ...
   }
}

最佳答案

伙计,“不友好”在这个数组上是轻描淡写的!

好吧,我想我明白了:

NSArray *dataRows = @[
                      @{ @"row" : @"1",
                         @"row_values" : @[
                                           @{ @"property_id" : @"47cc67093475061e01000542",
                                              @"property_value" : @"Mr." },
                                           @{ @"property_id" : @"47cc67093475061e01000540",
                                              @"property_value" : @"Male" }
                                          ]
                       },
                      @{ @"row" : @"2",
                         @"row_values" : @[
                                           @{ @"property_id" : @"47cc67093475061e01000542",
                                              @"property_value" : @"Ms." },
                                           @{ @"property_id" : @"47cc67093475061e01000540",
                                              @"property_value" : @"Female" }
                                          ]
                       }
                     ];

NSPredicate *p = [NSPredicate predicateWithFormat:@"SUBQUERY(row_values, $rv, $rv.property_id = %@ AND $rv.property_value = %@).@count > 0", @"47cc67093475061e01000540", @"Male"];

NSArray *filtered = [dataRows filteredArrayUsingPredicate:p];

因此,让我们看看该谓词在做什么。
  • 从最外层开始:
    SUBQUERY([stuff]).@count > 0
    
    SUBQUERY返回一个对象数组。我们将在SUBQUERY数组中的每个NSDictionary上运行此dataRows,并且我们希望汇总该词典中SUBQUERY返回某些内容的所有字典。因此,我们运行SUBQUERY,然后(因为它返回一个集合),询问它中有多少项(.@count),然后查看它是否大于0。如果是,则顶级字典将位于最终过滤后的数组。
  • 切入SUBQUERY:
    SUBQUERY(row_values, $rv, $rv.property_id = %@ AND $rv.property_value = %@)
    

    每个SUBQUERY都有三个参数:键路径,变量和谓词。关键路径是我们将要迭代的对象的属性。由于SUBQUERY是在最外面的字典上进行评估的,因此我们将要求该字典的@"row_values"并返回一个数组。然后,SUBQUERY将遍历row_values集合中的项目。

    变量就是我们将调用集合中每个项目的东西。在这种情况下,它将只是$rv(“行值”的简写)。在我们的例子中,每个$rv将是一个NSDictionary,因为row_values“property”是一个字典数组。

    最后,将执行谓词,依次替换每个字典的$rv。在这种情况下,我们要查看字典是否具有特定的property_id和特定的property_value。如果是这样,它将被聚合到一个新的数组中,这就是将从SUBQUERY 返回的数组。

    换句话说,SUBQUERY将建立一个包含所有row_values的数组,这些数组具有我们想要的property_idproperty_value

  • 最后,当我运行此代码时,我得到:
    (
            {
            row = 1;
            "row_values" =         (
                            {
                    "property_id" = 47cc67093475061e01000542;
                    "property_value" = "Mr.";
                },
                            {
                    "property_id" = 47cc67093475061e01000540;
                    "property_value" = Male;
                }
            );
        }
    )
    

    关于iphone - NSPredicate子查询语法,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/9630237/

    10-10 21:02