如何使用OR子句在Swift中过滤数组

时间:2016-07-08 15:58:06

标签: arrays swift filter optional

我试图通过匹配用户名或全名来过滤Swift中的对象数组。

   filteredRegUserArray = regUserArray.filter {
                $0.userName.lowercaseString.hasPrefix(lowercasePrefix) || 
                $0.fullName.lowercaseString.hasPrefix(lowercasePrefix)}

1 个答案:

答案 0 :(得分:4)

您的方案

所以看起来你有像我这样的结构(或类)

struct User {
    let userName: String?
    let fullName: String?
}

您还拥有一组用户

let users = [User]()

您的问题

现在,当您尝试过滤数组时

let lowercasePrefix = "abc"

let filtered = users.filter {
    $0.userName.lowercaseString.hasPrefix(lowercasePrefix) == true
    || $0.fullName.lowercaseString.hasPrefix(lowercasePrefix) == true
}

你得到一个错误。

解释

这种情况正在发生,因为userNamefullName被定义为选项。在这种情况下,您不能简单地编写$0.userName.lowercaseString,因为编译器无法确定userName内是否存在值。它会阻止您在lowercaseString值上读取nil属性,以防止崩溃。

您的(错误的)解决方案

您似乎修复了以这种方式更改结构的问题

struct User {
    var userName: String = " "
    var fullName: String = " "

    init(userName:String, fullName:String) {
        self.userName = userName
        self.fullName = fullName
    }
}

我说这很难看。这也是斯威夫特从一开始就试图战斗的东西。我们的想法是,您应该从不使用0empty String(或者在这种情况下奇怪地为blank space之类的值)来表示缺少价值。 缺少价值必须用nil表示。 因此,虽然这个解决方案确实可以编译,但从设计的角度来看它很糟糕,将来可能会给你带来一些问题。

解决方案1 ​​

永远不要接受nil

属性的User
struct User {
    let userName: String
    let fullName: String
}

let users = [User]()

let lowercasePrefix = "abc"

let filtered = users.filter {
    $0.userName.lowercaseString.hasPrefix(lowercasePrefix) == true
    || $0.fullName.lowercaseString.hasPrefix(lowercasePrefix) == true
}

解决方案2

如果用户的nil值为userNamefullName(这是您的应用,只有您可以回答此问题),那么只需管理这种可能性

struct User {
    let userName: String?
    let fullName: String?
}

let users = [User]()

let lowercasePrefix = "abc"

let filtered = users.filter {
    $0.userName?.lowercaseString.hasPrefix(lowercasePrefix) == true
    || $0.fullName?.lowercaseString.hasPrefix(lowercasePrefix) == true
}