Использование NSPredicate для фильтрации NSArray на основе ключей NSDictionary - PullRequest
94 голосов
/ 06 июня 2009

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

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

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

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

NSArray *filteredArray = [data filteredArrayUsingPredicate:predicate];

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

Однако я не смог найти пример.

Спасибо


Обновление

Я добавил кавычки вокруг искомой строки.

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

Всё равно не работает.


Обновление 2

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

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

Ответы [ 6 ]

150 голосов
/ 06 июня 2009

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

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

Отфильтровано в этом случае содержит словарь.

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

27 голосов
/ 26 августа 2012

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

Из документации Apple: like [cd] означает «нечувствительный к регистру и диакритике like».) Полное описание строкового синтаксиса и список всех доступных операторов см. в Формат предиката String Syntax .

11 голосов
/ 01 августа 2013
#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;
}
3 голосов
/ 06 июня 2009

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

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

0 голосов
/ 29 марта 2017

В 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"]]
0 голосов
/ 06 июня 2009

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

...