objective-c 使用 NSPredicate 根据 NSDictionary 键过滤 NSArray
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/958622/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Using NSPredicate to filter an NSArray based on NSDictionary keys
提问by Corey Floyd
I have an array of dictionaries.
我有一系列字典。
I want to filter the array based on a key.
我想根据键过滤数组。
I tried this:
我试过这个:
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(SPORT == %@)", @"Football"];
NSArray *filteredArray = [data filteredArrayUsingPredicate:predicate];
This doesn't work, I get no results. I think I'm doing something wrong. I know this is the method if "SPORT" was an ivar. I think it is probably different if it is a key.
这不起作用,我没有得到任何结果。我想我做错了什么。如果“SPORT”是 ivar,我知道这就是方法。我认为如果它是一把钥匙,它可能会有所不同。
I haven't been able to find an example however.
然而,我一直无法找到一个例子。
Thanks
谢谢
Update
更新
I added quotes around the string I am searching for.
我在要搜索的字符串周围添加了引号。
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(SPORT == '%@')", @"Football"];
It still does not work.
它仍然不起作用。
Update 2
更新 2
Solved it. I actually had to remove the single quotes, which seems to go against what the guide says.
解决了。我实际上不得不删除单引号,这似乎与指南所说的背道而驰。
My real problem is I had a nested array and I wasn't actually evaluating the dictionaries. Bone head move.
我真正的问题是我有一个嵌套数组,我实际上并没有评估字典。骨头动。
回答by suraken
It should work - as long as the data variable is actually an array containing a dictionary with the key SPORT
它应该可以工作 - 只要数据变量实际上是一个包含带有键 SPORT 的字典的数组
NSArray *data = [NSArray arrayWithObject:[NSMutableDictionary dictionaryWithObject:@"foo" forKey:@"BAR"]];
NSArray *filtered = [data filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"(BAR == %@)", @"foo"]];
Filtered in this case contains the dictionary.
在这种情况下过滤包含字典。
(the %@ does not have to be quoted, this is done when NSPredicate creates the object.)
(%@ 不必被引用,这是在 NSPredicate 创建对象时完成的。)
回答by ChargedNeuron
I know it's old news but to add my two cents. By default I use the commands LIKE[cd]rather than just [c]. The [d]compares letters with accent symbols. This works especially well in my Warcraft App where people spell their name "Vòódòó" making it nearly impossible to search for their name in a tableview. The [d]strips their accent symbols during the predicate. So a predicate of @"name LIKE[CD] %@", object.namewhere object.name == @"voodoo"will return the object containing the name Vòódòó.
我知道这是旧消息,但要加上我的两分钱。默认情况下,我使用命令LIKE[cd]而不仅仅是[c]. 在[d]比较了重音符号的字母。这在我的魔兽应用程序中特别有效,人们拼写他们的名字“Vòódòó”使得在 tableview 中搜索他们的名字几乎不可能。该[d]谓词中去掉他们的口音符号。所以@"name LIKE[CD] %@", object.namewhere的谓词object.name == @"voodoo"将返回包含名称 Vòódòó 的对象。
From the Apple documentation: like[cd] means “case- and diacritic-insensitive like.”) For a complete description of the string syntax and a list of all the operators available, see Predicate Format String Syntax.
来自 Apple 文档:like[cd] 表示“不区分大小写和变音符号的like。”)有关字符串语法的完整说明和所有可用运算符的列表,请参阅谓词格式字符串语法。
回答by Isaak Osipovich Dunayevsky
#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;
}
回答by Rod
NSPredicateis only available in iPhone 3.0.
NSPredicate仅适用于 iPhone 3.0。
You won't notice that until try to run on device.
在尝试在设备上运行之前,您不会注意到这一点。
回答by Imanou Petit
With Swift 3, when you want to filter an array of dictionaries with a predicate based on dictionary keys and values, you may choose one of the following patterns.
在 Swift 3 中,当您想使用基于字典键和值的谓词过滤字典数组时,您可以选择以下模式之一。
#1. Using NSPredicateinit(format:arguments:)initializer
#1. 使用NSPredicateinit(format:arguments:)初始化程序
If you come from Objective-C, init(format:arguments:)offers a key-value coding style to evaluate your predicate.
如果您来自 Objective-C,则init(format:arguments:)提供一种键值编码风格来评估您的谓词。
Usage:
用法:
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. Using NSPredicateinit(block:)initializer
#2. 使用NSPredicateinit(block:)初始化程序
As an alternative if you prefer strongly typedAPIs over stringly typedAPIs, you can use init(block:)initializer.
作为替代,如果您更喜欢强类型API 而不是字符串类型API,您可以使用init(block:)初始化程序。
Usage:
用法:
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"]]
回答by Martin Gordon
Looking at the NSPredicate reference, it looks like you need to surround your substitution character with quotes. For example, your current predicate reads: (SPORT == Football)You want it to read (SPORT == 'Football'), so your format string needs to be @"(SPORT == '%@')".
查看NSPredicate 参考,看起来您需要用引号将替换字符括起来。例如,您当前的谓词读取:(SPORT == Football)您希望它读取(SPORT == 'Football'),因此您的格式字符串需要是@"(SPORT == '%@')"。

