【问题标题】:Swift: Combine condition and if-let with logical orSwift:将条件和 if-let 与逻辑或结合起来
【发布时间】:2016-04-29 10:28:49
【问题描述】:

我正在尝试做一些逻辑上看起来像这样的事情:

if text == "" || let i = Int(text) where i < 2 {
   // do something; don't care about the value of i
}

当然,这不是一个有效条件——如果 text == "" 是持有的部分,i 的值是什么?但是,由于我只对 where 子句中的 i 的值感兴趣,我希望有一种很好的方法可以达到相同的效果,即如果任一条件成立,则执行相同的闭包。我目前的解决方案是提取闭包并从两个单独的 if 块中调用它,但这看起来很麻烦。

【问题讨论】:

    标签: ios iphone swift swift2


    【解决方案1】:

    与您的代码示例等效的是:

    if text == "" || Int(text) ?? 2 < 2 {
        print("valid")
        // do your previous "something
    } else {
        print("invalid")
    }
    

    产生

    "" -> 有效
    “1” -> 有效
    “2” -> 无效
    “abc” -> 无效

    【讨论】:

    • 呃,“abc”打印valid,因为nil &lt; 2
    • @vacawama 正确:/ 修复它,现在它不再那么漂亮了。
    • 聪明!如果我需要右侧更复杂的条件(我需要),任何“无效”数字都将在 ?? 之后执行。
    • @PBosman 如果您需要更复杂的条件,您可能不会将它们放入 if 结构内的一行中。 ?? 部分用于规避 vacawama 指出的问题:如果 Int(text) 返回 nil,则将其“替换”为 2,否则使用实际返回值。这样,与 2 的比较总是会产生正确的结果。
    【解决方案2】:

    如果您经常进行这种比较,您可以创建自己的运算符,以便将可选项与代表您成功条件的给定闭包进行比较。如果解包后的值满足条件,则返回 true,否则返回 false。

    例如:

    infix operator ?& {precedence 130 }
    func ?&<T>(lhs: T?, @noescape rhs:(T)->Bool) -> Bool {
        return lhs != nil ? rhs(lhs!) : false
    }
    
    ...
    
    if text == "" || Int(text) ?& {$0 < 2}  {
        print("valid")
    } else {
        print("invalid")
    }
    

    您也可以重载现有的 &lt; 运算符来执行此操作,但这可能会影响依赖 nil 小于非可选值的现有代码。

    func <<T:Comparable>(lhs: T?, rhs:T) -> Bool {
        return lhs != nil ? (lhs! < rhs) : false
    }
    
    ...
    
    if text == "" || Int(text) < 2  {
        print("valid")
    } else {
        print("invalid")
    }
    

    【讨论】:

      【解决方案3】:

      也许使用map 来处理可选值更“快捷”。本质上,mapping 一个可选值会在闭包中为您提供一个未包装的值,然后您可以对其进行修改以返回您需要的值。在闭包之外,您将收到修改后的值,如果原始可选项为 nil,您将收到 nil。

      let optInt: Int? = 1 // or nil
      let incremented: Int? = optInt.map { $0 + 1 }
      // If optInt isn't nil, its incremented value is returned by map.
      // If it is nil, map just returns nil.
      

      所以要解决我的问题,我可以这样做:

      if text == "" || Int(text).map({$0 < 2}) ?? false {
         // If text has an Int value, the map closure will return
         // whether that value is less than 2.
         // Else, map will return nil, which we coalesce to false.
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-06-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-03-30
        • 2020-06-08
        • 1970-01-01
        相关资源
        最近更新 更多