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

Kse*_*vin 0 arrays filter optional swift

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

   filteredRegUserArray = regUserArray.filter {
                $0.userName.lowercaseString.hasPrefix(lowercasePrefix) || 
                $0.fullName.lowercaseString.hasPrefix(lowercasePrefix)}
Run Code Online (Sandbox Code Playgroud)

Luc*_*tti 6

你的场景

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

struct User {
    let userName: String?
    let fullName: String?
}
Run Code Online (Sandbox Code Playgroud)

您还有一系列用户

let users = [User]()
Run Code Online (Sandbox Code Playgroud)

你的问题

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

let lowercasePrefix = "abc"

let filtered = users.filter {
    $0.userName.lowercaseString.hasPrefix(lowercasePrefix) == true
    || $0.fullName.lowercaseString.hasPrefix(lowercasePrefix) == true
}
Run Code Online (Sandbox Code Playgroud)

你得到一个错误。

说明

发生这种情况是因为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
    }
}
Run Code Online (Sandbox Code Playgroud)

让我说这很丑陋。这也是斯威夫特从一开始就试图与之抗争的事情。这个想法是你永远不应该使用一个值 like0或 an empty String(或者奇怪的blank space是在这种情况下是alike )来表示没有值。值的缺失必须用 表示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
}
Run Code Online (Sandbox Code Playgroud)

解决方案2

如果用户可以具有nil作为userName或的值fullName(它是您的应用程序,只有您可以回答这个问题),那么只需管理这种可能性

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
}
Run Code Online (Sandbox Code Playgroud)