仅当不是nil时才使用选项作为过滤器

时间:2017-09-06 19:10:32

标签: swift

假设我在Swift中有一个名为MyObject的类,它有一堆String属性(例如)namehometownfavoriteColor。我有一个MyObject数组,我基本上想要根据某些属性过滤数组。因此,当我定义我的过滤参数时,我将它们定义为选项,如果可选项是nil,我假设我不想沿着该属性进行过滤。我如何优雅地为多个属性编写此代码?

var list: [MyObject] = [some array here]

class MyObject {
    var name: String
    var hometown: String
    var favouriteColor: String

    init(name: String, hometown: String, favouriteColor: String) {
        self.name = name
        self.hometown = hometown
        self.favouriteColor = favouriteColor        
    }
 }

这就是上面的课程。假设我正在操场上编写一个函数来过滤。我可以不加思索地写这个。

func filter(name: String?, hometown: String?, favouriteColor: String?) {
    var filteredObjects : [MyObject]? = list
    if (name != null) {
       filteredObjects = filteredObjects.filter($0.name == name)
    }
    if (hometown != null) {
       filteredObjects = filteredObjects.filter($0.hometown == hometown)
    }

}

也许我会将上述内容称为filter(name: nil, hometown: nil, favouriteColor: "blue")

我想我所问的是,如果我上面提出的建议甚至能够发挥作用,如果有的话,是否有更优雅的方式来做呢?

2 个答案:

答案 0 :(得分:1)

鉴于你的课程

class MyObject {
    let name: String?
    let hometown: String?
    let favouriteColor: String?

    init(name: String?, hometown: String?, favouriteColor: String?) {
        self.name = name
        self.hometown = hometown
        self.favouriteColor = favouriteColor        
    }
}

和你的数组

let elms: [MyObject] = []

解决方案1 ​​

您可以像这样进行过滤

let filtered = elms.filter { $0.name != nil && $0.hometown != nil && $0.favouriteColor != nil }

解决方案2

或者你可以在课堂内移动逻辑

class MyObject {
    let name: String?
    let hometown: String?
    let favouriteColor: String?

    init(name: String?, hometown: String?, favouriteColor: String?) {
        self.name = name
        self.hometown = hometown
        self.favouriteColor = favouriteColor
    }

    var allFieldsPopulated: Bool {
        return name != nil && hometown != nil && favouriteColor != nil
    }
}

现在你可以简单地写

let filtered = elms.filter { $0.allFieldsPopulated }

性能(短路评估)

&&表达式的右侧仅在左侧I true时进行评估。

所以写作

name != nil && hometown != nil && favouriteColor != nil

表示如果名称为nil,则仅评估表达式的name != nil部分。

答案 1 :(得分:0)

如果你只是想找一个更好的方法来写这个条件,这里有几个建议:

func filter(name: String?, hometown: String?, favouriteColor: String?) 
{
    filteredObjects = list.filter 
    { 
           $0.name           == name           ?? $0.name
        && $0.hometown       == hometown       ?? $0.hometown
        && $0.favouriteColor == favouriteColor ?? $0.favouriteColor
    }
}

func filter(name: String?, hometown: String?, favouriteColor: String?) 
{
    func criteria(_ value:String?, matches field:String) -> Bool
    { return value == nil || value! == field }

    filteredObjects = list.filter 
    { 
          criteria(name,           matches: $0.name)
       && criteria(hometown,       matches: $0.hometown)
       && criteria(favouriteColor, matches: $0.favouriteColor)
    }
}