Использование NSPredicate для фильтрации NSArray на основе ключей NSDictionary
У меня есть набор словарей.
Я хочу фильтровать массив на основе ключа.
Я пробовал это:
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(SPORT == %@)", @"Football"];
NSArray *filteredArray = [data filteredArrayUsingPredicate:predicate];
Это не работает, я не получаю никаких результатов. Я думаю, что я делаю что-то неправильно. Я знаю, что это метод, если "СПОРТ" был иваром. Я думаю, что это, вероятно, другое, если это ключ.
Однако мне не удалось найти пример.
Спасибо
Обновление
Я добавил кавычки вокруг строки, которую я ищу.
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(SPORT == '%@')", @"Football"];
Он по-прежнему не работает.
Обновление 2
Решил. Я действительно должен был удалить одиночные кавычки, которые, похоже, противоречат тому, что говорит гид.
Моя реальная проблема в том, что у меня был вложенный массив, и я фактически не оценивал словари. Движение головки костей.
Ответы
Ответ 1
Он должен работать - до тех пор, пока переменная данных на самом деле представляет собой массив, содержащий словарь с ключом SPORT
NSArray *data = [NSArray arrayWithObject:[NSMutableDictionary dictionaryWithObject:@"foo" forKey:@"BAR"]];
NSArray *filtered = [data filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"(BAR == %@)", @"foo"]];
Отфильтрованный в этом случае словарь содержит слова.
(% @не нужно указывать, это делается, когда NSPredicate создает объект.)
Ответ 2
Я знаю это старые новости, но добавляю свои два цента. По умолчанию я использую команды LIKE[cd]
, а не только [c]
. [d]
сравнивает буквы с символами акцента. Это особенно хорошо работает в моем приложении Warcraft, где люди называют свое имя "Vòódòó", что делает невозможным поиск их имени в виде таблицы. [d]
разбивает свои символы акцента во время предиката. Таким образом, предикат @"name LIKE[CD] %@", object.name
, где object.name == @"voodoo"
возвращает объект, содержащий имя Vòódòó.
Из документации Apple:
например, [cd] означает "case и diacritic-insensitive like." ). Полное описание синтаксиса строк и список всех доступных операторов см. в разделе Строка форматирования предикатов Синтаксис.
Ответ 3
#import <Foundation/Foundation.h>
// clang -framework Foundation Siegfried.m
int
main() {
NSArray *arr = @[
@{@"1" : @"Fafner"},
@{@"1" : @"Fasolt"}
];
NSPredicate *p = [NSPredicate predicateWithFormat:
@"SELF['1'] CONTAINS 'e'"];
NSArray *res = [arr filteredArrayUsingPredicate:p];
NSLog(@"Siegfried %@", res);
return 0;
}
Ответ 4
NSPredicate
доступен только в iPhone 3.0.
Вы не заметите этого, пока не попытаетесь запустить на устройстве.
Ответ 5
С Swift 3, если вы хотите отфильтровать массив словарей с предикатом на основе клавиш и значений словаря, вы можете выбрать один из следующих шаблонов.
Если вы пришли из Objective-C, init(format:arguments:)
предлагает стиль кодирования ключевого значения для оценки вашего предиката.
Использование:
import Foundation
let array = [["key1": "value1", "key2": "value2"], ["key1": "value3"], ["key3": "value4"]]
let predicate = NSPredicate(format: "key1 == %@", "value1")
//let predicate = NSPredicate(format: "self['key1'] == %@", "value1") // also works
let filteredArray = array.filter(predicate.evaluate)
print(filteredArray) // prints: [["key2": "value2", "key1": "value1"]]
# 2. Использование NSPredicate
init(block:)
initializer
В качестве альтернативы, если вы предпочитаете строго типизированные API-интерфейсы поверх строго типизированных API-интерфейсов, вы можете использовать инициализатор init(block:)
.
Использование:
import Foundation
let array = [["key1": "value1", "key2": "value2"], ["key1": "value3"], ["key3": "value4"]]
let dictPredicate = NSPredicate(block: { (obj, _) in
guard let dict = obj as? [String: String], let value = dict["key1"] else { return false }
return value == "value1"
})
let filteredArray = array.filter(dictPredicate.evaluate)
print(filteredArray) // prints: [["key2": "value2", "key1": "value1"]]
Ответ 6
Глядя на ссылка NSPredicate, похоже, вам нужно окружить свой символ замещения кавычками. Например, ваш текущий предикат читает: (SPORT == Football)
Вы хотите, чтобы он читал (SPORT == 'Football')
, поэтому ваша строка формата должна быть @"(SPORT == '%@')"
.