我有一系列结构,我不知道如何使用结构参数之一进行搜索。
我的结构看起来像:
struct Actor {
var name: String!
var posterURL: String!
init(_ dictionary: [String: Any]) {
name = dictionary["name"] as! String
posterURL = dictionary["image"] as! String
}
}
所以,我试图使用谓词
let actorSearchPredicate = NSPredicate(format: "name contains[c] %@", text)
filterredActors = (actors as NSArray).filtered(using: actorSearchPredicate)
但是,当我尝试键入任何内容时,它会因错误而崩溃
[<_SwiftValue 0x10657ffb0> valueForUndefinedKey:]: this class is not key value coding-compliant for the key name.'
对结构使用谓词搜索的正确方法是什么? 谢谢
答案 0 :(得分:1)
如果您需要使用谓词来过滤结构,则可以在不进入@objc
区域或将数据转换为NSArray
的情况下执行此操作:
func filter(actors: [Actor], named: String) -> [Actor] {
let predicate = NSPredicate(format: "SELF contains[cd] %@", named)
return actors.filter {
predicate.evaluate(with: $0.name)
}
}
示例:
struct Actor {
let name: String
let imdb: String
}
let actors = [
Actor(name: "John Travolta", imdb: "http://www.imdb.com/name/nm0000237"),
Actor(name: "Uma Thurman", imdb: "http://www.imdb.com/name/nm0000235"),
Actor(name: "Samuel L. Jackson", imdb: "http://www.imdb.com/name/nm0000 168"),
Actor(name: "Penélope Cruz", imdb: "http://www.imdb.com/name/nm0004851"),
Actor(name: "Penelope Ann Miller", imdb: "http://www.imdb.com/name/nm0000542")
]
print(filter(actors: actors, named: "Uma").map { $0.name })
// ["Uma Thurman"]
print(filter(actors: actors, named: "J").map { $0.name })
// ["John Travolta", "Samuel L. Jackson"]
使用谓词进行过滤很有用,例如,考虑变音符号。让我们用重音字符搜索一个演员名字:
print(filter(actors: actors, named: "Penelope").map { $0.name })
// ["Penélope Cruz", "Penelope Ann Miller"]
它找到了“Penelope”,带有和不带有重音的“e”。
在这种情况下,使用String.contains
将不起作用:
let text = "Penelope"
let hits = actors.filter { ( $0.name.lowercased().contains(text.lowercased()) )}
print(hits.map { $0.name })
// ["Penelope Ann Miller"]
有更好的选择(String
本地化搜索,正则表达式,String.range(of:options:range:locale)
,...)。使用谓词不会更快(也不会慢很多)。如果您已经知道,使用谓词语法可能更容易推理复杂查询。
答案 1 :(得分:1)
NSPredicate
,Swift有方便的方法来检查 不区分大小写
whether the receiver contains a given string by performing a case insensitive, locale-aware search.
filterredActors = actors.filter { $0.name.localizedCaseInsensitiveContains(text) }
和 案例和变音符号不敏感
filterredActors = actors.filter { $0.name.localizedStandardContains(text) }