Swift 4 Struct按参数搜索包含

时间:2018-01-12 20:03:22

标签: arrays swift search struct predicate

我有一系列结构,我不知道如何使用结构参数之一进行搜索。

我的结构看起来像:

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.'

对结构使用谓词搜索的正确方法是什么? 谢谢

2 个答案:

答案 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) }

案例和变音符号不敏感

  

whether the receiver contains a given string by performing a case and diacritic insensitive, locale-aware search.

filterredActors = actors.filter { $0.name.localizedStandardContains(text) }