使用NSPredicate根据NSDictionary键过滤NSArray

时间:2009-06-06 00:03:05

标签: objective-c cocoa nsarray nsdictionary nspredicate

我有一系列词典。

我想根据键过滤数组。

我试过了:

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

NSArray *filteredArray = [data filteredArrayUsingPredicate:predicate];

这不起作用,我没有结果。我想我做错了什么。我知道如果“SPORT”是一个ivar,这就是方法。我认为如果它是一把钥匙可能会有所不同。

然而,我无法找到一个例子。

由于


更新

我在我正在搜索的字符串周围添加了引号。

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

它仍然不起作用。


更新2

解决了它。我实际上不得不删除单引号,这似乎与指南所说的相反。

我真正的问题是我有一个嵌套数组,而我实际上并没有评估字典。骨头移动。

6 个答案:

答案 0 :(得分:150)

它应该可以工作 - 只要数据变量实际上是一个包含关键字SPORT

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

在这种情况下过滤包含字典。

(%@不必引用,这是在NSPredicate创建对象时完成的。)

答案 1 :(得分:27)

我知道这是旧闻,但要加我的两分钱。默认情况下,我使用命令LIKE[cd]而不仅仅是[c][d]将字母与重音符号进行比较。这在我的魔兽应用程序中特别有效,人们将其名称拼写为“Vòódòó”,因此几乎不可能在桌面视图中搜索他们的名字。 [d]在谓词期间删除其重音符号。所以@"name LIKE[CD] %@", object.name的谓词,其中object.name == @"voodoo"将返回包含名称Vòódòó的对象。

来自Apple文档: 像[cd]表示“case-and diacritic-insensitive like。”。有关字符串语法的完整描述以及所有可用运算符的列表,请参阅Predicate Format String Syntax

答案 2 :(得分:11)

#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 :(得分:3)

NSPredicate仅适用于iPhone 3.0。

在尝试在设备上运行之前,您不会注意到这一点。

答案 4 :(得分: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"]]

答案 5 :(得分:-1)

查看NSPredicate reference,看起来您需要用引号括住替换字符。例如,您当前的谓词为:(SPORT == Football)您希望它读取(SPORT == 'Football'),因此您的格式字符串必须为@"(SPORT == '%@')"