【问题标题】:Convert String to Bool in Swift - via API or most Swift-like approach在 Swift 中将 String 转换为 Bool - 通过 API 或大多数类似 Swift 的方法
【发布时间】:2015-03-22 07:46:08
【问题描述】:

是否有一个 API 可以转换布尔值的大多数可能的字符串表示形式(例如“True”、“true”、“False”、“false”、“yes”、“no”、“1”、“0”)在 Swift 中变成 Bool?

如果不是,那么从头开始编码最类似于 Swift 的方法是什么?它会是一个功能性的 map() 操作吗?还是别的什么?

此实例中的原始源数据是 JSON,但我对以最类似于 Swift 的方式解决问题的关键点感兴趣,从而在此过程中更多地了解该语言。

【问题讨论】:

    标签: swift boolean


    【解决方案1】:
     var st = "false"
    
     extension String {
       func toBool() -> Bool{
        if self == "false" {
            return false
        }else{
            return true
        }
    }
    }
    
     if st.toBool() == false {
         println("its ok")
     }
    

    【讨论】:

    • 虽然这可能会回答这个问题,但您并没有留下任何关于为什么这样做的解释。对于以后可能遇到相同问题的访问者,此答案并没有增加太多价值。请扩展您的答案以包括一些解释。
    • 你可以简单地返回 self == "false",然后在 toBool() 中不需要 if 语句
    【解决方案2】:

    在 Objective-C 中,我们有一个字符串的 boolValue。如果 Swift 中不存在,您可以将字符串转换为 NSString 然后使用它

    var aString = NSString(string: "tRue")
    
    var b = aString.boolValue
    

    如果 aString.upperCase == "TRUE",b 应该返回 true

    更新: Info(仅在苹果 API 中看到):

    var boolValue: Bool { get } // Skips initial space characters (whitespaceSet), or optional -/+ sign followed by zeroes. Returns YES on encountering one of "Y", "y", "T", "t", or a digit 1-9. It ignores any trailing characters.
    

    更新 2: 我用扩展方法对此方法进行了性能测试。这种方法的表现令人印象深刻。这是我的测试代码,我在 GCD 线程中调用了这些函数,使用模拟器,一个接一个。

    dispatch_async(dispatch_queue_create("com.haduyenhoa.test", nil), {
                self.test1()
                self.test2()
            })
    
    
    func test1() {
        let testTrue: String = "TRue"
        let testFalse: String = "faLse"
    
        let testNil: String = "whoops!"
    
        let begin : NSDate = NSDate()
    
        NSLog("BEGIN native")
        var testTrueObjC: NSString
        var testFalseObjC : NSString
        var testNilObjC:NSString
    
        for index in 1...100000 {
            testTrueObjC = NSString(string:testTrue)
             testFalseObjC = NSString(string:testFalse)
            testNilObjC = NSString(string:testNil)
    
            var b1 = testTrueObjC.boolValue // {Some true}
    
            var b2 = testFalseObjC.boolValue // {Some false}
            var b3 = testNilObjC.boolValue // nil
        }
        let end : NSDate = NSDate()
        let interval = end.timeIntervalSinceDate(begin)
       NSLog("DURATION native: \(interval)")
    }
    
    func test2() {
        let testTrue: String = "TRue"
        let testFalse: String = "faLse"
    
        let testNil: String = "whoops!"
    
        let begin : NSDate = NSDate()
        NSLog("BEGIN extension")
        for index in 1...100000 {
            var b1 = testTrue.boolValue() // {Some true}
            var b2 = testFalse.boolValue() // {Some false}
            var b3 = testNil.boolValue() // nil
        }
        let end : NSDate = NSDate()
        let interval = end.timeIntervalSinceDate(begin)
        NSLog("DURATION extension: \(interval)")
    
    }
    

    控制台日志:

    2015-03-12 14:16:23.238 testSwift3[2343:298787] BEGIN native
    2015-03-12 14:16:23.543 testSwift3[2343:298787] DURATION native: 0.305041968822479
    2015-03-12 14:16:23.543 testSwift3[2343:298787] BEGIN extension
    2015-03-12 14:16:35.360 testSwift3[2343:298787] DURATION extension: 11.8166469931602
    

    我们可以通过简化规则来提高扩展解决方案的性能。性能取决于我们如何实施规则。

    【讨论】:

    • 我认为这是要走的路。类型转换为 NSString,然后使用 .boolValue。您还可以通过将 self 类型转换为 NSString 然后调用 boolValue 在字符串的扩展中执行此操作。有没有人对这种关于性能的事情有任何意见?像其他答案一样用字符串比较来写会更快吗?
    • 哇。那是一个巨大的差异。我的问题实际上是关于使用类型转换为 NSString 然后使用 bool 值与人们自己的实现以及字符串比较,如@Kirsteins 答案(这可能是你的扩展中的内容)。无论如何,这里的区别是巨大的,但是你已经实现了你的扩展,它肯定比原生使用 NSStrings 慢得多。我想知道是什么让它变得这么慢......
    • 扩展名取自 Para 的回答。正如我所说,这取决于我们如何实现我们的扩展。我认为从 String (swift) 到 NSString (Objective-C) 的转换并不重。
    • 好的,感谢您对此进行调查。看到性能差异很有趣。
    • 您有指向您引用的 API 的链接吗?
    【解决方案3】:

    没有内置方式 AFAIK。与标准toInt() 类似的方法可能是:

    extension String {
        var bool: Bool? {
            switch self.lowercased() {
            case "true", "t", "yes", "y":
                return true
            case "false", "f", "no", "n", "":
                return false
            default:
                if let int = Int(string) {
                    return int != 0
                }
                return nil
            }
        }
    }
    

    【讨论】:

    • 我已经在 switch self 中添加了一个“switch self.lowercased()”,因为你不能期望这些值总是以正确的大小写形式出现。 func toBool() -> 布尔? { switch self.lowercased() { case "true", "yes", "1": return true case "false", "no", "0": return false default: return nil } }
    • 这作为一个计算属性会更好。只需将func toBool() -> Bool? 替换为var bool: Bool?
    【解决方案4】:

    正如已经建议的那样,我将构建String 的扩展,仅列出您想要转换为truefalse 的字符串文字,为不转换的内容保留nil 大小写(或在这种情况下也返回false?你的选择!)。顺便说一句,您可能不希望您的方法区分大小写。

    例如:

    extension String {
        func boolValue() -> Bool? {
            let trueValues = ["true", "yes", "1"]
            let falseValues = ["false", "no", "0"]
    
            let lowerSelf = self.lowercaseString
    
            if contains(trueValues, lowerSelf) {
                return true
            } else if contains(falseValues, lowerSelf) {
                return false
            } else {
                return nil
            }
        }
    }
    
    let testTrue: String = "TRue"
    testTrue.boolValue() // {Some true}
    let testFalse: String = "faLse"
    testFalse.boolValue() // {Some false}
    let testNil: String = "whoops!"
    testNil.boolValue() // nil
    

    如果您使用NSString 对象及其boolValue() 方法,请小心,因为如果遇到“Y”、“y”、“T”、“t”或数字 1-,它将返回 true 9 (See docs here)。

    举个例子:

    let nsString = NSString(string: "tFalse")
    nsString.boolValue // true
    

    【讨论】:

      【解决方案5】:

      使用这个,

      self.boolType = NSString(string:stringType!).boolValue
      

      【讨论】:

        【解决方案6】:

        类型转换和一个不错的字符串扩展,你就可以开始运行了

        extension String {
        var boolValue: Bool {
            return (self as NSString).boolValue
        }}
        

        【讨论】:

        • 这是最简单的解决方案,对于小型字符串集,任何性能损失都很小。
        • 我想说这是一个很好的解决方案......但唯一的问题是它会返回 false 也适用于任何不能翻译成布尔值 (例如“狗”、“猫”、“xyz”)。对于这种情况,您可能需要nil
        • 我如何访问它?例如,如果我的函数通常返回一个布尔值,即它执行return false,我如何使用此扩展名执行return "No match"?谢谢。
        • "No match" 不是布尔值,你不应该使用这个函数。布尔值只是是或否。
        • @TokyoToo 如果您需要一个超越简单的true / false 的状态,那么您是否应该考虑改用enum
        【解决方案7】:

        可选字符串的单行解决方案

        let value:String? = "put some string or even just nil here"
        let trueOrFalse = NSString(string: value ?? "").boolValue
        

        【讨论】:

          【解决方案8】:

          我将 @Kirsteins 代码重构为带有字符串值的 Bool 初始化程序

          extension Bool {
          
              init?(string: String) {
                  switch string {
                  case "True", "true", "yes", "1":
                      self = true
                  case "False", "false", "no", "0":
                      self = false
                  default:
                      return nil
                  }
              }
          
          }
          
          
          // tests
          let one = Bool(string: "SDASD") // nil
          let two = Bool(string: "0") // false
          let three = Bool(string: "true") // true
          let four = Bool(string: "null") // nil
          

          【讨论】:

            【解决方案9】:

            以上答案的结论:

            您可以对简单的一行进行扩展和使用。

            斯威夫特 3

            extension String {
                func boolValueFromString() -> Bool {
                    return NSString(string: self).boolValue
                }
            }
            

            用法

             if (dictCardData.value(forKey: "isadmin") as! String).boolValueFromString() {
                // Stuff
            }
            

            【讨论】:

              【解决方案10】:

              如果你用过一次,试试这个。

              let str:String = "1"
              
              var boo:Bool = str == "1" || str == "true" || str == "True" || str == "yes"
              

              【讨论】:

                【解决方案11】:

                我更喜欢这种处理可选字符串并且默认值为 false 的实现

                extension Bool {
                    init(_ string: String?) {
                        guard let string = string else { self = false; return }
                
                        switch string.lowercased() {
                        case "true", "yes", "1":
                            self = true
                        default:
                            self = false
                        }
                    }
                }
                

                【讨论】:

                  【解决方案12】:

                  我采用了 Nicolas Manzini 的解决方案并稍作修改。我推荐使用 cast 操作符,因为它是 String 和 NSString 之间的桥梁。不知道它是否是免费的桥,但它应该比盲目地创建一个新对象有更好的性能。

                  extension String {
                  
                      var boolValue: Bool {
                          return (self as NSString).boolValue
                      }
                  }
                  

                  【讨论】:

                  • lo,我刚刚修改了我的答案,发现你也提出了这个解决方案。起来!
                  【解决方案13】:

                  没有其他答案涉及完整或混合大写字符串的可能性。那么为什么不接受 Kirsteins 的回答,将其与一些计算属性魔法和 shazam 混合:

                  extension String {
                      var bool: Bool? {
                          let lowercaseSelf = self.lowercased()
                  
                          switch lowercaseSelf {
                          case "true", "yes", "1":
                              return true
                          case "false", "no", "0":
                              return false
                          default:
                              return nil
                          }
                      }
                  }
                  

                  用法如下:

                  let trueBoolString = "TRUE"   // or "True", "true", "YES", "yEs", and so on
                  print(trueBoolString.bool)    // true
                  

                  【讨论】:

                    【解决方案14】:
                    // Bool to String
                    var bool = true                         // true
                    var string = String(describing: bool)   // "true"
                    
                    // String to Bool
                    bool = Bool(string) ?? false            // true
                    string = String(describing: bool)       // "true"
                    
                    

                    【讨论】:

                      【解决方案15】:

                      我认为最简单的方法是:

                      let someString = "true"
                      let convertedBool = Bool(someString) ?? false
                      

                      【讨论】:

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