Swift中如何基于多个属性过滤数组

3
struct User{
    var firstName:String
    var lastName:String
    var city:String
    var email:String
}

var users = [User]

我正在尝试在文本字段中输入时过滤用户。就像搜索电子邮件一样。它应该显示所有匹配的结果,但不应重复相同的用户。我能够根据一个属性(例如name)过滤数组,但不确定如何基于所有属性过滤数组。
我已经实现了UITextField代理并使用以下代码进行过滤:
let filteredArray = users.filter({ (user) -> Bool in
    return user.firstName.lowercased().contains(“John”)
})

6
可能是按多个数组条件筛选的重复问题。 - undefined
2
让我们思考一下filter()闭包的含义。你遍历数组,当前元素在这里被命名为user(这是参数)。然后,根据user的值,你决定返回true以保留它,或者返回false以舍弃它。目前,如果firstName.lowercased()包含"John",你返回true。那么,使用OR运算符来检查另一个属性呢? - undefined
@Larme 我从来没有想过使用OR。你是对的。谢谢 - undefined
你可以使用AND,这完全取决于保留元素的原因是什么。它可能是一个“复杂”的原因。 - undefined
如果你想增加匹配项的数量,请使用(||)。如果你只想匹配满足所有条件的项目,请使用(&&)。 - undefined
虽然无关紧要,但是firstName.range(of: "John", options: .caseInsensitive) != nilfirstName.lowercased().contains(“John”)更高效。 - undefined
3个回答

5
let filteredArray = users.filter({ $0.firstName.lowercased().contains("firstName") || $0.lastName.lowercased().contains("lastName") || ... })

这是一行非常长的代码。最好将其拆分开来。 - undefined

2

您可以设置多个条件,并使用OR(||)或AND(&&)将它们组合在一起-这是一个简单的布尔值,您可以将其视为if语句中的布尔值-

if user.firstName.lowercased().contains("john") || user.lastName.lowerCased().contains("lastname") { return true }
else { return false }

因此,在您的代码中,它应该像这样:

let filteredArray = users.filter { (user) -> Bool in
return user.firstName.lowercased().contains("john") || user.lastName.lowercased().contains("lastname") }

1
不要写成 if b { return true } else { return false }。直接写成 return b - undefined
它并没有澄清任何问题,只是增加了无关的冗余。 - undefined
这样做是因为这种语法可能会让初学者感到困惑,所以我将其转换为一个简单的if语句。很多初学者在理解if语句实际上由一个布尔值组成时会遇到问题。 - undefined
从绝对初学者的角度来看,你的代码更加复杂。它需要理解布尔值、if语句和返回语句,而我建议的代码只需要理解返回语句。 - undefined
初学者不认为"user.firstName.lowercased().contains("john") || user.lastName.lowerCased().contains("lastname")"是一个单一的布尔参数"b"。 - undefined
让我们在聊天室继续此讨论 - undefined

2

由于您可能需要搜索多个内容,我建议您创建一个Searchable协议,并通过检查它们的任何组成部分是否匹配来使聚合类型可搜索。

import Foundation

struct User {
    let firstName: String
    let lastName: String
    let city: String
    let email: String
    let age: Int // an example of a non-String type.
}

protocol Searchable {
    func matches(query: String) -> Bool 
}

extension String: Searchable {
    func matches(query: String) -> Bool {
        // Implement any kind of searching algorithm here. Could be as smart as fuzzy seraching
        // or as basic as this case-insenitive simple substring search
        return self.lowercased().contains(query)
    }
}

extension Int: Searchable {
    func matches(query: String) -> Bool {
        return String(self).matches(query: query)
    }
}


extension User: Searchable {
    func matches(query: String) -> Bool {
        let constituents: [Searchable] = [firstName, lastName, city, email, age]
        return constituents.contains(where: { $0.matches(query: query) })
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接