Использование NSPredicate для фильтрации NSArray на основе ключей NSDictionary

StackOverflow https://stackoverflow.com/questions/958622

Вопрос

У меня есть массив словарей.

Я хочу отфильтровать массив по ключу.

Я попробовал это:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(SPORT ==  %@)", @"Football"];

NSArray *filteredArray = [data filteredArrayUsingPredicate:predicate];

Это не работает, я не получаю никаких результатов.Я думаю, что делаю что-то не так.Я знаю, что это метод, если «СПОРТ» был иваром.Я думаю, что, вероятно, все будет по-другому, если это ключ.

Однако мне не удалось найти пример.

Спасибо


Обновлять

Я добавил кавычки вокруг строки, которую ищу.

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(SPORT ==  '%@')", @"Football"];

Это все еще не работает.


Обновление 2

Решил это.На самом деле мне пришлось удалить одинарные кавычки, что, похоже, противоречит тому, что говорит руководство.

Моя настоящая проблема в том, что у меня был вложенный массив, и я фактически не оценивал словари.Движение кости головы.

Это было полезно?

Решение

Это должно работать - пока переменная данных на самом деле является массивом, содержащим словарь с ключом SPORT.

NSArray *data = [NSArray arrayWithObject:[NSMutableDictionary dictionaryWithObject:@"foo" forKey:@"BAR"]];    
NSArray *filtered = [data filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"(BAR == %@)", @"foo"]];

Фильтрация в этом случае содержит словарь.

(%@ не обязательно заключать в кавычки, это делается, когда NSPredicate создает объект.)

Другие советы

Я знаю, что это старые новости, но добавлю свои два цента.По умолчанию я использую команды LIKE[cd] а не просто [c][d] сравнивает буквы с символами ударения.Это особенно хорошо работает в моем приложении Warcraft, где люди пишут свое имя «Vòódòó», что делает практически невозможным поиск их имени в виде таблицы.А [d] удаляет символы акцента во время сказуемого.Итак, предикат @"name LIKE[CD] %@", object.name где object.name == @"voodoo" вернет объект, содержащий имя Vòódòó.

Из документации Apple:Like[cd] означает «независимо от регистра и диакритических знаков».) Полное описание синтаксиса строк и список всех доступных операторов см. Синтаксис строки формата предиката.

#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;
}

NSPredicate доступно только в iPhone 3.0.

Вы не заметите этого, пока не попытаетесь запустить на устройстве.

В Swift 3, если вы хотите отфильтровать массив словарей с помощью предиката на основе ключей и значений словаря, вы можете выбрать один из следующих шаблонов.


№1.С использованием NSPredicate init(format:arguments:) инициализатор

Если вы пришли из 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:) инициализатор

В качестве альтернативы, если вы предпочитаете строго типизированный 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"]]

Глядя на Ссылка на NSPPredicate, похоже, вам нужно заключить символ замены в кавычки.Например, ваш текущий предикат гласит: (SPORT == Football) Вы хотите, чтобы это читалось (SPORT == 'Football'), поэтому ваша строка формата должна быть @"(SPORT == '%@')".

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top