NSPredicate子查询语法

时间:2012-03-09 07:08:23

标签: iphone ios nsarray nspredicate

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

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

[dataRows filterUsingPredicate:lookupPredicate];

这不返回任何值。我尝试了各种形式的任何形式,但我似乎找不到任何可以解析的东西。同样,目标是仅保留那些外部数组字典,其中内部数组字典内容的任何内容的谓词都为真。我可以看到我在弄清楚这个工作的咒语上花了一天时间...任何想法?

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.";
           },
 ...
   }
}

2 个答案:

答案 0 :(得分:21)

男人,“不友好”是对这个阵列的轻描淡写!

好吧,我想我想出来了:

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

让我们看看这个谓词在做什么。

  1. 从最外层开始:

    SUBQUERY([stuff]).@count > 0
    

    SUBQUERY返回一个对象数组。我们将在SUBQUERY数组中的每个NSDictionary上运行此dataRows,并且我们希望聚合该字典上的SUBQUERY返回的所有字典东西。所以我们运行SUBQUERY,然后(因为它返回一个集合),询问它中有多少项(.@count)并查看它是否大于0.如果是,那么顶级字典将位于最终过滤的数组中。

  2. 深入了解SUBQUERY

    SUBQUERY(row_values, $rv, $rv.property_id = %@ AND $rv.property_value = %@)
    

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

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

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

    所以说以不同的方式,SUBQUERY将构建一个包含我们正在寻找的property_idproperty_value的所有row_values的数组。 / p>

  3. 最后,当我运行此代码时,我得到:

    (
            {
            row = 1;
            "row_values" =         (
                            {
                    "property_id" = 47cc67093475061e01000542;
                    "property_value" = "Mr.";
                },
                            {
                    "property_id" = 47cc67093475061e01000540;
                    "property_value" = Male;
                }
            );
        }
    )
    

答案 1 :(得分:0)

Apple的SUBQUERY文档分散在几个地方。

  

子查询表达式的字符串格式为:

     

SUBQUERY(collection_expression, variable_expression, predicate);

     

其中expression是一个计算集合的谓词表达式,variableExpression是一个表达式,用于包含集合的每个单独元素,而谓词是用于确定元素是否属于结果集合的谓词。

有关详细信息和示例,请参阅my answer to a similar question about the documentation for SUBQUERY syntax

相关问题