【问题标题】:Swift switch statement on a tuple of optional booleans可选布尔元组上的 Swift switch 语句
【发布时间】:2014-08-18 23:56:20
【问题描述】:

我无法弄清楚如何在开关内的元组内使用选项。下面的 .Some(let ...) ... 语法作为非元组工作,但在元组中我得到了预期的分隔符:(

var dict = Dictionary<String,Bool>()
dict["a"] = true

switch (dict["a"],dict["b") {
case (.Some(let a) where !a, .Some(let b) where b):
  println("false/nil, true")
case (.Some(let a) where a, .Some(let b) where !b):
  println("true, false/nil")

我想避免做以下事情

    if let a = self.beaconList["a"] {
        if let b = self.beaconList["b"] {
            // a, b
        } else {
            // a, !b
        }
    } else {
        if let b = self.beaconList["b"] {
            // !a, b
        } else {
            // !a, !b
        }
    }

【问题讨论】:

    标签: switch-statement swift tuples optional


    【解决方案1】:

    简化!

    var dict = Dictionary<String,String>()
    
    dict["a"] = "the letter a"
    
    switch (dict["a"],dict["b"]) {
      case (.None, let b):
        println("false/nil, true \(b)")
      case (let a, .None):
        println("true, false/nil \(a)")
      default:
        println("don't know") 
    }
    

    【讨论】:

    • 此处的操作:我想匹配 nil/false (我认为 .None 可以)或 true。不幸的是,“let a”或“let b”也允许 nil/false :(,所以我需要找到一种不同的方法来做到这一点。
    【解决方案2】:

    有很多方法可以做到这一点,但要从字面上修复您尝试执行的操作的语法,您需要通过匹配 .Some(false) 或使用 ! (我认为这有点奇怪,你会看到)

    var dict = Dictionary<String,Bool>()
    dict["a"] = true
    dict["c"] = false
    
    func matchOneOrTheOtherWithOptionals(a: Bool?, b: Bool?) -> String {
        switch (a, b) {
        case (.Some(true), let b) where b == .None || !b!: // gross
            return "a was true, but b was None or false"
        case (let a, .Some(true)) where a == .None || a == .Some(false):
            return "a was None or false and b was true"
        default:
            return "They both had a value, or they were both missing a value"
        }
    }
    
    matchOneOrTheOtherWithOptionals(true, .None) // "a was true, but b was None or false"
    matchOneOrTheOtherWithOptionals(true, false) // "a was true, but b was None or false"
    matchOneOrTheOtherWithOptionals(.None, true) // "a was None or false and b was true"
    matchOneOrTheOtherWithOptionals(false, true) // "a was None or false and b was true"
    
    matchOneOrTheOtherWithOptionals(false, false) // "They both had a value, or they were both missing a value"
    matchOneOrTheOtherWithOptionals(true, true) // "They both had a value, or they were both missing a value"
    matchOneOrTheOtherWithOptionals(.None, .None) // "They both had a value, or they were both missing a value"
    

    您也可以尝试以下方法:

    func noneToFalse(bool: Bool?) -> Bool {
        if let b = bool {
            return b
        } else {
            return false
        }
    }
    
    func matchOneOrTheOther(a: Bool, b: Bool) -> String {
        switch (a, b) {
        case (true, false):
            return "a is true, b was false or None"
        case (false, true):
            return "a was false/None, b was true"
        default:
            return "both were true, or both were false/None"
        }
    }
    
    matchOneOrTheOther(noneToFalse(dict["a"]), noneToFalse(dict["b"]))
    

    这是我在撰写此答案时使用的 Playground 的要点:https://gist.github.com/bgrace/b8928792760159ca58a1

    【讨论】:

    • 您可以通过使用 matchOneOrTheOtherWithOptionals(a: Bool!, b: Bool!)ab args 隐式展开选项来避免 !b! 的粗俗。那么你的案例wheres 就变成了 where b == .none || !b:where a == .none || !a:。在这里这样做是完全安全的,因为在使用包装的布尔值之前,您要明确检查 ab 是否有 .none
    【解决方案3】:

    接受的答案已过期。所以我用 Swift 5 重写了它。

        var dict = Dictionary<String,Bool>()
        dict["a"] = true
        dict["c"] = false
    
        func matchOneOrTheOtherWithOptionals(_ a: Bool?, _ b: Bool?) -> String {
            switch (a, b) {
            case (.some(true), .none), (.some(true), .some(false)):
                return "a was true, but b was None or false"
            case (.none, .some(true)), (.some(false), .some(true)):
                return "a was None or false and b was true"
            default:
                return "They both had a value, or they were both missing a value"
            }
        }
    
        let xs: [Bool?] = [true, false, .none]
        for a in xs {
            for b in xs {
                print("a = \(String(describing: a)), b=\(String(describing: b))")
                print(matchOneOrTheOtherWithOptionals(a,b))
            }
        }
    

    【讨论】:

      猜你喜欢
      • 2013-10-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多