Если все словари имеют одинаковый набор ключей, то вы можете сделать что-то довольно простое:
NSArray *keys = ...; //the list of keys that all of the dictionaries contain
NSMutableArray *subpredicates = [NSMutableArray array];
for (NSString *key in keys) {
NSPredicate *subpredicate = [NSPredicate predicateWithFormat:@"%K contains[cd] %@", key, searchText];
[subpredicates addObject:subpredicate];
}
NSPredicate *filter = [NSCompoundPredicate orPredicateWithSubpredicates:subpredicates];
Затем вы можете использовать filter
для фильтрации NSArray
(используя -filteredArrayUsingPredicate
).
Если, с другой стороны, у вас есть массив произвольных словарей с разными ключами, вам нужно что-то более извращенное:
NSPredicate *filter = [NSPredicate predicateWithFormat:@"SUBQUERY(FUNCTION(SELF, 'allKeys'), $k, SELF[$k] contains[cd] %@).@count > 0", searchText];
Немногоо том, что это делает:
FUNCTION(SELF, 'allKeys')
- это выполнит -allKeys
на SELF
(NSDictionary
) и вернет NSArray
всех ключей в словаре SUBQUERY(allKeys, $k, SELF[$k] contains[cd] %@)
- это будет повторять каждый элемент в allKeys
, каждый последующий элемент помещается в переменную $k
.Для каждого элемента будет выполнено SELF[$k] contains %@
.Это в конечном итоге будет делать: [theDictionary objectForKey:$k] contains[cd] %@
.Если это возвращает YES
, то элемент $k
будет агрегирован в новый массив. SUBQUERY(...).@count > 0
- после нахождения всех ключей, соответствующих значениям, которые содержат ваш текст поиска, мы проверяем ипосмотрим, были ли они.Если они есть (т. Е. Размер массива больше 0), тогда весь словарь будет частью окончательного отфильтрованного массива.
Я рекомендую использовать первый подход, если привсе возможно.SUBQUERY
и FUNCTION
немного загадочны, и первое из них намного легче для понимания.
И вот еще один способ, который вы фактически почти имели в своем вопросе.Вместо ANY SELF.allValues contains[cd] %@
вы можете ANY FUNCTION(SELF, 'allValues') contains[cd] %@
.Это эквивалентно моему безумию, но намного проще.Спасибо вам за то, что вы думаете об использовании ANY
(я обычно забываю, что он существует).
EDIT
Причина, по которой SELF.allValues
не работает, заключается в том, чтоэто интерпретируется как путь к ключу, и -[NSDictionary valueForKey:]
должен быть таким же, как -[NSDictionary objectForKey:]
.Подвох в том, что если вы добавите к ключу @
, то он перейдет к [super valueForKey:]
, что будет делать то, что вы ожидаете.Таким образом, вы действительно могли бы сделать:
ANY SELF.@allValues contains[cd] %@
Или просто:
ANY @allValues contains[cd] %@
И это будет работать (и это лучший и самый простой подход).