使用 NSPredicate 根据 NSDictionary 键过滤 NSArray
Posted
技术标签:
【中文标题】使用 NSPredicate 根据 NSDictionary 键过滤 NSArray【英文标题】:Using NSPredicate to filter an NSArray based on NSDictionary keys 【发布时间】:2010-10-31 19:29:40 【问题描述】:我有一个字典数组。
我想根据一个键过滤数组。
我试过了:
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(SPORT == %@)", @"Football"];
NSArray *filteredArray = [data filteredArrayUsingPredicate:predicate];
这不起作用,我没有得到任何结果。我想我做错了什么。如果“SPORT”是 ivar,我知道这就是方法。如果是钥匙的话,我想可能会有所不同。
但是我找不到一个例子。
谢谢
更新
我在要搜索的字符串周围添加了引号。
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(SPORT == '%@')", @"Football"];
还是不行。
更新 2
解决了。我实际上不得不删除单引号,这似乎与指南所说的背道而驰。
我真正的问题是我有一个嵌套数组,我实际上并没有评估字典。骨头移动。
【问题讨论】:
只是提到谓词默认区分大小写(使用[c]变得不敏感)。 ios sorting array of dictionaries by key of inner dictionary的可能重复 【参考方案1】:它应该可以工作 - 只要数据变量实际上是一个包含带有键 SPORT 的字典的数组
NSArray *data = [NSArray arrayWithObject:[NSMutableDictionary dictionaryWithObject:@"foo" forKey:@"BAR"]];
NSArray *filtered = [data filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"(BAR == %@)", @"foo"]];
Filtered 在这种情况下包含字典。
(%@ 不必被引用,这是在 NSPredicate 创建对象时完成的。)
【讨论】:
NSPredicate 能否在 iPhone 上运行?它在 sim 上运行良好,但在 iPhone 上运行它会给出一个错误,即找不到 NSPredicate 类。 NSPredicate 从 iOS 3.0 开始可用。 为像我这样的新程序员澄清一下,代码的关键行是 'NSArray *filtered = [data filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"(BAR == %@)", @"foo" ]];'其中“数据”是您的代码中已经存在的 nsdictionaries 的 nsarray。 (谢谢你) 如果键名是动态的怎么办?【参考方案2】:我知道这是旧消息,但要加上我的两分钱。默认情况下,我使用命令LIKE[cd]
而不仅仅是[c]
。 [d]
将字母与重音符号进行比较。这在我的魔兽应用程序中特别有效,人们拼写他们的名字“Vòódòó”,几乎不可能在表格视图中搜索他们的名字。 [d]
在谓词中去掉了它们的重音符号。所以 @"name LIKE[CD] %@", object.name
的谓词,其中 object.name == @"voodoo"
将返回包含名称 Vòódòó 的对象。
来自 Apple 文档: like[cd] 表示“不区分大小写和变音符号的like”。)有关字符串语法的完整描述和所有可用运算符的列表,请参阅Predicate Format String Syntax。
【讨论】:
【参考方案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 中,当您想要使用基于字典键和值的谓词过滤字典数组时,您可以选择以下模式之一。
#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"]]
【讨论】:
【参考方案6】:查看NSPredicate reference,您似乎需要用引号将替换字符括起来。例如,您当前的谓词为:(SPORT == Football)
您希望它为(SPORT == 'Football')
,因此您的格式字符串需要为@"(SPORT == '%@')"
。
【讨论】:
我也认为它是这么说的。显然不需要引号。我不确定指南所说的“应该”用于什么。以上是关于使用 NSPredicate 根据 NSDictionary 键过滤 NSArray的主要内容,如果未能解决你的问题,请参考以下文章
如何根据多对关系集是不是包含特定值使用 NSPredicate 进行过滤