【问题标题】:Lesser than or greater than in Swift switch statement小于或大于 Swift switch 语句
【发布时间】:2015-10-17 20:21:22
【问题描述】:

我熟悉 Swift 中的 switch 语句,但想知道如何用 switch 替换这段代码:

if someVar < 0 {
    // do something
} else if someVar == 0 {
    // do something else
} else if someVar > 0 {
    // etc
}

【问题讨论】:

  • 虽然这是一个有趣的问题,但我认为使用 switch 的代码的可读性远不如 if 语句。仅仅因为你可以,并不意味着你应该。

标签: swift switch-statement


【解决方案1】:

我能想到的最干净的解决方案:

switch someVar {
case ..<0:
    // do something
case 0:
    // do something else
default:
    // etc
}

【讨论】:

    【解决方案2】:

    Swift 5 现在很干净

    switch array.count {
    case 3..<.max: 
        print("Array is greater than or equal to 3")
    case .min..<3:
        print("Array is less than 3")
    default:
        break
    }
    

    【讨论】:

      【解决方案3】:

      很高兴 Swift 4 解决了这个问题:

      作为 3 中的解决方法,我做了:

      switch translation.x  {
      case  0..<200:
          print(translation.x, slideLimit)
      case  -200..<0:
          print(translation.x, slideLimit)
      default:
          break
      }
      

      有效但不理想

      【讨论】:

        【解决方案4】:

        这就是范围的样子

        switch average {
        case 0..<40: //greater or equal than 0 and less than 40
            return "T"
        case 40..<55: //greater or equal than 40 and less than 55
            return "D"
        case 55..<70: //greater or equal than 55 and less than 70
            return "P"
        case 70..<80: //greater or equal than 70 and less than 80
            return "A"
        case 80..<90: //greater or equal than 80 and less than 90
            return "E"
        case 90...100: //greater or equal than 90 and less or equal than 100
            return "O"
        default:
            return "Z"
        }
        

        【讨论】:

          【解决方案5】:

          使用 Swift 5,您可以选择以下开关之一来替换您的 if 语句。


          #1 使用带有PartialRangeFromPartialRangeUpTo 的开关

          let value = 1
          
          switch value {
          case 1...:
              print("greater than zero")
          case 0:
              print("zero")
          case ..<0:
              print("less than zero")
          default:
              fatalError()
          }
          

          #2 使用带有ClosedRangeRange 的开关

          let value = 1
          
          switch value {
          case 1 ... Int.max:
              print("greater than zero")
          case Int.min ..< 0:
              print("less than zero")
          case 0:
              print("zero")
          default:
              fatalError()
          }
          

          #3 使用带 where 子句的 switch

          let value = 1
          
          switch value {
          case let val where val > 0:
              print("\(val) is greater than zero")
          case let val where val == 0:
              print("\(val) is zero")
          case let val where val < 0:
              print("\(val) is less than zero")
          default:
              fatalError()
          }
          

          #4 使用带有 where 子句的 switch 并赋值给 _

          let value = 1
          
          switch value {
          case _ where value > 0:
              print("greater than zero")
          case _ where value == 0:
              print("zero")
          case _ where value < 0:
              print("less than zero")
          default:
              fatalError()
          }
          

          #5 将 switch 与 RangeExpression 协议的 ~=(_:_:) 运算符一起使用

          let value = 1
          
          switch true {
          case 1... ~= value:
              print("greater than zero")
          case ..<0 ~= value:
              print("less than zero")
          default:
              print("zero")
          }
          

          #6 使用带有Equatable 协议的~=(_:_:) 运算符的开关

          let value = 1
          
          switch true {
          case value > 0:
              print("greater than zero")
          case value < 0:
              print("less than zero")
          case 0 ~= value:
              print("zero")
          default:
              fatalError()
          }
          

          #7 使用 switch 与 PartialRangeFromPartialRangeUpToRangeExpressioncontains(_:) 方法

          let value = 1
          
          switch true {
          case (1...).contains(value):
              print("greater than zero")
          case (..<0).contains(value):
              print("less than zero")
          default:
              print("zero")
          }
          

          【讨论】:

          • 为什么 #2 中需要默认大小写?如果范围是从 Int.min 到 Int.max ,那么还剩下什么?
          • 哇,不错的选项列表。很高兴知道有很多方法可以做到这一点。
          • 很好的概述,但有缺陷,因为 0 和 1 之间的数字下落不明。 0.1 引发致命错误,因为 1... 仅涵盖 1 中的数字。因此,此解决方案仅在 valueInt 时才有效,但这很危险,因为如果变量类型更改,功能会中断而没有任何编译器错误。
          • 您的解决方案不适用于 Double 类型。 case 1...: print("greater than zero") 不大于 0 大于等于 1。
          【解决方案6】:

          &lt;0 表达式不起作用(不再起作用?)所以我最终得到了这个:

          Swift 3.0:

          switch someVar {
              case 0:
                  // it's zero
              case 0 ..< .greatestFiniteMagnitude:
                  // it's greater than zero
              default:
                  // it's less than zero
              }
          

          【讨论】:

          • 在 swift 3.0 中,X_MAX 已被.greatestFiniteMagnitude 取代,即Double.greatestFiniteMagnitudeCGFloat.greatestFiniteMagnitude 等。所以通常情况下,您可以只使用case 0..&lt; .greatestFiniteMagnitude,因为someVar 的类型已经知道了
          • @Dorian Roy var timeLeft = 100 switch timeLeft {case 0...&lt;=7200: print("ok") default:print("nothing") } 为什么无法识别&lt;= 运算符?如果我在没有平等的情况下编写它,它会起作用。谢谢
          • @bibscy 您想使用封闭范围运算符:case 0...7200: 运算符&lt;= 是一个比较运算符。在 switch 中你只能使用范围操作符(see docs)
          • 这很棒。我收到此错误'Range' 类型的表达式模式无法匹配'Int' 类型的值,因为我的someVarInt,我必须这样做Double(someVar) ` 让它工作......
          【解决方案7】:

          这是一种方法。假设someVarInt 或其他Comparable,您可以选择将操作数分配给新变量。这使您可以使用 where 关键字随意调整范围:

          var someVar = 3
          
          switch someVar {
          case let x where x < 0:
              print("x is \(x)")
          case let x where x == 0:
              print("x is \(x)")
          case let x where x > 0:
              print("x is \(x)")
          default:
              print("this is impossible")
          }
          

          这可以简化一点:

          switch someVar {
          case _ where someVar < 0:
              print("someVar is \(someVar)")
          case 0:
              print("someVar is 0")
          case _ where someVar > 0:
              print("someVar is \(someVar)")
          default:
              print("this is impossible")
          }
          

          您还可以通过范围匹配完全避免 where 关键字:

          switch someVar {
          case Int.min..<0:
              print("someVar is \(someVar)")
          case 0:
              print("someVar is 0")
          default:
              print("someVar is \(someVar)")
          }
          

          【讨论】:

          • 我推荐default: fatalError() 尽早发现可能的逻辑错误。
          • 谢谢!这些示例非常有帮助,它们解决了我的问题! (其他例子也很好,但你的对我最有帮助)
          • @MartinR assertionFailure 似乎是一个更安全的选择,尤其是在团队合作时。
          【解决方案8】:

          你可以:

          switch true {
          case someVar < 0:
              print("less than zero")
          case someVar == 0:
              print("eq 0")
          default:
              print("otherwise")
          }
          

          【讨论】:

            【解决方案9】:

            switch 语句在后台使用~= 运算符。所以这个:

            let x = 2
            
            switch x {
            case 1: print(1)
            case 2: print(2)
            case 3..<5: print(3..<5)
            default: break
            }
            

            脱糖:

            if 1          ~= x { print(1) }
            else if 2     ~= x { print(2) }
            else if 3..<5 ~= x { print(3..<5) }
            else {  }
            

            If you look at the standard library reference, it can tell you exactly what the ~= is overloaded to do: 包括范围匹配和等价的东西。 (不包括枚举大小写匹配,这是一种语言特性,而不是标准库中的函数)

            您会发现它与左侧的直接布尔值不匹配。对于此类比较,您需要添加 where 语句。

            除非...您自己重载 ~= 运算符。 (这通常推荐)一种可能性是这样的:

            func ~= <T> (lhs: T -> Bool, rhs: T) -> Bool {
              return lhs(rhs)
            }
            

            这样就匹配了一个函数,该函数将左侧的布尔值返回到右侧的参数。以下是您可以使用它的类型:

            func isEven(n: Int) -> Bool { return n % 2 == 0 }
            
            switch 2 {
            case isEven: print("Even!")
            default:     print("Odd!")
            }
            

            对于您的情况,您可能有如下语句:

            switch someVar {
            case isNegative: ...
            case 0: ...
            case isPositive: ...
            }
            

            但现在您必须定义新的isNegativeisPositive 函数。除非你重载更多的运算符...

            您可以将普通中缀运算符重载为柯里化前缀或后缀运算符。这是一个例子:

            postfix operator < {}
            
            postfix func < <T : Comparable>(lhs: T)(_ rhs: T) -> Bool {
              return lhs < rhs
            }
            

            这将像这样工作:

            let isGreaterThanFive = 5<
            
            isGreaterThanFive(6) // true
            isGreaterThanFive(5) // false
            

            将它与前面的函数结合起来,你的 switch 语句可以如下所示:

            switch someVar {
            case 0< : print("Bigger than 0")
            case 0  : print("0")
            default : print("Less than 0")
            }
            

            现在,您可能不应该在实践中使用这种东西:它有点狡猾。您(可能)最好坚持使用where 声明。也就是说,

            的switch语句模式
            switch x {
            case negative:
            case 0:
            case positive:
            }
            

            switch x {
            case lessThan(someNumber):
            case someNumber:
            case greaterThan(someNumber):
            }
            

            似乎很常见,值得考虑。

            【讨论】:

            • 您对这个问题的回答在哪里?我找不到它。
            • case 3..
            【解决方案10】:

            由于有人已经发布了case let x where x &lt; 0:,这里可以替代someVarInt

            switch someVar{
            case Int.min...0: // do something
            case 0: // do something
            default: // do something
            }
            

            这里是someVarDouble 的替代方案:

            case -(Double.infinity)...0: // do something
            // etc
            

            【讨论】:

              猜你喜欢
              • 2011-10-03
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2015-12-11
              • 2018-09-27
              • 2013-09-01
              • 2015-07-29
              相关资源
              最近更新 更多