NSPredicate子查询语法

mic*_*ael 5 iphone nsarray nspredicate ios

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

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

[dataRows filterUsingPredicate:lookupPredicate];
Run Code Online (Sandbox Code Playgroud)

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

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.";
           },
 ...
   }
}
Run Code Online (Sandbox Code Playgroud)

Dav*_*ong 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];
Run Code Online (Sandbox Code Playgroud)

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

  1. 从最外层开始:

    SUBQUERY([stuff]).@count > 0
    
    Run Code Online (Sandbox Code Playgroud)

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

  2. 挖掘到SUBQUERY:

    SUBQUERY(row_values, $rv, $rv.property_id = %@ AND $rv.property_value = %@)
    
    Run Code Online (Sandbox Code Playgroud)

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

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

    最后,谓词将被执行,$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;
            }
        );
    }
)
Run Code Online (Sandbox Code Playgroud)