【问题标题】:Combine an IF LET with an OR in Swift在 Swift 中将 IF LET 与 OR 结合
【发布时间】:2018-05-24 14:55:11
【问题描述】:

有没有一种优雅的方法可以通过 or 运算符组合两个 if let 语句。例如,我需要检查字符串“pass”、“true”或整数 1。下面的函数就是这样做的......

func test(content: Any) -> String {
    if let stringValue = (content as? String)?.lowercased(),
        ["pass", "true"].contains(stringValue) {
        return "You Passed"
    }
    if let numValue = (content as? Int),
        1 == numValue {
        return "YOU PASSED"
    }
    return "You Failed"
}

test(content: "Pass") //"You Passed"
test(content: 1) //"YOU PASSED"

结合这两个 if let 语句来处理传入的数据的最简单方法是什么?

【问题讨论】:

  • 第二个if let 可以作为else if 的情况添加到第一个,因为两者是互斥的。
  • 理想情况下,您应该让函数仅返回 Bool,然后让第二个函数将其转换为 String,但具有 3 个值,即使具有不同的类型表示相同,也似乎是设计问题本身。尽量避免Any
  • "YOU PASSED" - 与 "You Passed" 不同,所以似乎不需要 OR 运算符。

标签: swift if-statement simplify any


【解决方案1】:

你不能用 an or inside 做一个 if let 因为如果它因为一个条件而进入语句,另一个可以是 nil,并且使用 if let 你确保 var 在语句中不是 nil .

我会检查它们是否不为零并做一些事情。

即使在此示例中,您也不需要使用 if let。 (我用一个来展示如何使用 AND 运算符,使用 OR 是不可能的。

if let stringValue = (content as? String)?.lowercased(), (["pass", "true"].contains(stringValue) || 1 == (numValue ?? 0)) {
        return "You Passed"
    }

此外,根据 SwiftLint,如果您只想检查变量的值是否为 nil,最好使用 != nil 而不是 if let。

【讨论】:

    【解决方案2】:

    你可能只需要内联所有内容:

    func test(content: Any) -> String {
        if ["pass", "true"].contains((content as? String)?.lowercased())
            || (content as? Int) == 1 {
            return "You Passed"
        }
        return "You Failed"
    }
    

    但总的来说,我建议将这些内容拆分为多种方法,一种检查值,第二种将其转换为String

    func test(content: Any) -> Bool {
       return ["pass", "true"].contains((content as? String)?.lowercased())
           || (content as? Int) == 1
    }
    
    func testToString(content: Any) -> String {
       return test(content: content) ? "You passed" : "You failed"
    }
    

    您还可以先将所有值转换为 String 并检查:

    func test(content: Any) -> Bool {
        let stringValue = String(describing: content).lowercased()
    
        return ["1", "pass", "true"].contains(stringValue)
    }
    

    但是,这会增加一些误报,因为即使对于 "1" 字符串,它也会返回 true,我通常建议不要这样做。

    【讨论】:

      【解决方案3】:

      遇到了类似的问题,想合并两个let try? 分配以保持代码 DRY。得到它的工作,但需要确保括号正确:

      if let number = try? ((try? Number.parse("1")) ?? Number.parse("2")) {
          print("Yay, a number: \(number)")
      } else {
          print("Nope, not a number")
      }
      
      // => Prints "Yay, a number: 1"
      
      if let number = try? ((try? Number.parse("a")) ?? Number.parse("2")) {
          print("Yay, a number: \(number)")
      } else {
          print("Nope, not a number")
      }
      
      // => Prints "Yay, a number: 2"
      

      我在这个示例中模拟了以下内容,在实际代码中我使用 PhoneNumberKit 解析了一个数字。

      struct Number {
          static func parse(_ numberString: String) throws -> Int {
              if let result = Int(numberString) {
                  return result
              } else {
                  throw ParsingError.notANumber
              }
          }
      
          enum ParsingError: Error {
              case notANumber
          }
      }
      

      【讨论】:

        【解决方案4】:

        很明显,当我回答这个问题并且没有仔细阅读它时,我分心了。不,您使用 2 个可选绑定 if let 语句编写一个表达式,其中只有一个为真。

        你不能说

        如果让 x = y 让 a = b

        似乎最干净的方法是使用 else:

        if let x = y { code }
        else if let a = b { other code } 
        

        未回答所提问题的上一个答案:

        是的,您可以组合多个 if let 语句:

        var x: Int? = 1
        var y: String? = ""
        var z = 2
        
        if let x = x,
          let y = y,
          z == 2 {
            //do stuff
        }
        

        上面的 if 块只会在 x 和 y 不为 nil (且 z == 2)时执行

        更好的是,每个后续的 if let 可选绑定都可以使用您与前一个 if let 展开的可选绑定。

        【讨论】:

        • 您使用的是 AND 运算符而不是 Or,无法将 if let 与 Or 运算符结合。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-05-28
        • 1970-01-01
        • 1970-01-01
        • 2015-02-09
        • 1970-01-01
        • 2016-12-10
        相关资源
        最近更新 更多