Человек, "недружелюбный" - преуменьшение этого массива!
ОК, думаю, я понял это:
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
A 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
является массивом словарей.
Наконец, предикат будет выполнен с заменой $rv
для каждого словаря по очереди. В этом случае мы хотим посмотреть, есть ли в словаре определенный property_id
и определенный property_value
. Если он делает , он будет объединен в новый массив , и это будет массив, который будет возвращен из SUBQUERY
.
Другими словами, SUBQUERY
собирается построить массив всех значений row_values, которые имеют property_id
и property_value
того, что мы ищем.
И, наконец, когда я запускаю этот код, я получаю:
(
{
row = 1;
"row_values" = (
{
"property_id" = 47cc67093475061e01000542;
"property_value" = "Mr.";
},
{
"property_id" = 47cc67093475061e01000540;
"property_value" = Male;
}
);
}
)