使用NSPredicate根据NSDictionary键过滤NSArray


94

我有很多字典。

我想根据一个键过滤数组。

我尝试了这个:

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

NSArray *filteredArray = [data filteredArrayUsingPredicate:predicate];

这行不通,我没有结果。我想我做错了。我知道如果“ SPORT”是ivar,这就是方法。我认为如果是密钥,可能会有所不同。

我还没有找到一个例子。

谢谢


更新资料

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

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

它仍然不起作用。


更新2

解决了。实际上,我不得不删除单引号,这似乎与指南中所说的背道而驰。

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


仅提及谓词默认情况下区分大小写(使用[c]变得不敏感)。
groumpf

Answers:


151

它应该起作用-只要数据变量实际上是一个包含带有键SPORT的字典的数组

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

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

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


NSPredicate是否可以在iPhone上使用?它在sim卡上运行良好,但在iPhone上运行时却提示找不到NSPredicate类的错误。
lostInTransit

从iOS 3.0开始提供NSPredicate。
zekel 2012年

1
为了澄清像我这样的新编码员,代码的关键所在是'NSArray * filtered = [datafilteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@“((BAR ==%@)”,@“ foo”]];';' 其中“数据”是代码中已存在的nsdictionaries的nsarray。(谢谢您,谢谢)
tmr

如果键名是动态的怎么办?
iPeter

27

我知道这是个老新闻,但要加上我的两分钱。默认情况下,我使用命令LIKE[cd]而不是[c]。在[d]比较了重音符号的字母。在我的《魔兽争霸》应用程序中,这尤其有效,因为人们在拼写他们的名字“Vòódòó”后,几乎不可能在表格视图中搜索他们的名字。[d]在谓词中,条带去除其重音符号。因此,谓词将@"name LIKE[CD] %@", object.name在何处object.name == @"voodoo"返回包含名称Vòódòó的对象。

从Apple文档中获得:like [cd]表示“不区分大小写和变音符号。”)有关字符串语法的完整说明和所有可用运算符的列表,请参阅谓词格式字符串语法


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

NSPredicate 仅在iPhone 3.0中可用。

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


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"]]

-1

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


我也这么认为。显然不需要引号。我不确定指南所说的引号“应该”用于什么。
科里·弗洛伊德
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.