对多个“ if case”语句使用“或”逻辑

时间:2018-12-04 21:18:32

标签: swift enums boolean-logic associated-value

假设我有一个带有关联值的枚举案例,以及该枚举类型的两个变量:

enum MyEnum {
    case foo, bar(_ prop: Int)
}

let var1 = MyEnum.foo
let var2 = MyEnum.bar(1)

如果我要检查两个变量是否都与具有关联值的一般情况相匹配,则可以用逗号来做到:

if case .bar = var1, case .bar = var2 {
    print("both are bar")
}

但是我需要检查哪一个是否匹配大小写,如下所示:

if case .bar = var1 || case .bar = var2 {
    print("at least one is bar")
}

但是,这不能编译。还有另一种方法可以使逻辑起作用?

4 个答案:

答案 0 :(得分:6)

我将对枚举本身使用某种isBar属性,以便使“ a或b”测试保持可读性:

enum MyEnum {
    case foo, bar(_ prop: Int)

    var isBar: Bool {
        switch self {
        case .bar: return true
        default: return false
        }
    }
}

let var1 = MyEnum.foo
let var2 = MyEnum.bar(1)

let eitherIsBar = var1.isBar || var2.isBar

答案 1 :(得分:2)

您必须为枚举实现Equatable协议:

extension MyEnum: Equatable {}
func ==(lhs: MyEnum, rhs: MyEnum) -> Bool {
    switch (lhs, rhs) {
        case (let .bar(prop1), let .bar(prop2)):
            return prop1 == prop2
        case (.foo, .foo):
        return true

     default:
         return false
    }
}

然后以下代码应该起作用:

if var1 == .bar(1) || var2 == .bar(1) {
    print("at least one is bar")
}

UPD:如果不需要检查关联值,则可以执行以下模式匹配:

switch (var1, var2) {
case (.bar, _), (_, .bar): print("at least one is bar")
default: break
}

答案 2 :(得分:0)

我的猜测是if caseguard case是语法糖,并且只是编译器支持的一个小功能,可以改善开发人员的体验。在第一种情况下,您使用的是连续条件,这也只是一种语言功能,可以代替&&运算符以使代码更具可读性。当您使用&&||运算符时,编译器将期望获得两个返回布尔值的表达式。 case .bar = var1本身并不完全是可以单独存在的表达式,在Swift中没有上下文,因此它不被视为返回布尔值的表达式。

总结:

  • if caseguard case只是语法糖,可以与if <expression>, <expression>语法一起使用

  • &&||只是逻辑运算符,它们基本上是一个期望在两侧都有两个布尔参数的函数。

要解决您的问题,请使用良好的旧switch语句。 希望对您有所帮助。

答案 3 :(得分:0)

我对这种事情的解决方案是:

如果[var1,var2] .contains(.bar){

很多时候,我都希望采用另一种方式,一个可能根据多个值过滤的单个变量:

如果[.bar,.baz]。包含(var)

但是,确实,如果涉及到相关的值,则必须使它们相等,并定义一个运算符。