web-dev-qa-db-fra.com

Convertir une chaîne en Bool dans Swift - via une API ou une approche similaire à celle de Swift

Existe-t-il une API permettant de convertir le plus grand nombre possible de représentations sous forme de chaîne de valeurs booléennes ("True", "true", "False", "false", "yes", "no", "1", "0") à Swift?

Sinon, quelle serait l'approche la plus Swift-like pour coder cela à partir de zéro? S'agirait-il d'une opération fonctionnelle map ()? Ou autre chose?

Les données source originales dans cet exemple sont JSON, mais je m'intéresse au cœur de résoudre le problème de la manière la plus rapide possible et d'en apprendre davantage sur le langage utilisé.

55
Andrew Ebling

Il n'y a pas construit de manière AFAIK. Une méthode similaire à la norme toInt() pourrait être:

extension String {
    var bool: Bool? {
        switch self.lowercased() {
        case "true", "t", "yes", "y", "1":
            return true
        case "false", "f", "no", "n", "0":
            return false
        default:
            return nil
        }
    }
}
77
Kirsteins

En Objective-C, nous avons boolValue pour une chaîne. Vous pouvez convertir votre chaîne en NSString puis l'utiliser, si elle n'existe pas dans Swift

var aString = NSString(string: "tRue")

var b = aString.boolValue

b doit retourner true si aString.upperCase == "TRUE"

Mise à jour: pour info (vu dans l'API Apple):

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.

Mise à jour 2: J'ai effectué un test de performance de cette méthode avec la méthode d'extension. La performance de cette méthode est impressionnante. Voici le code de mon test, j'ai appelé ces fonctions dans un thread GCD, en utilisant simulateur, l'une après l'autre.

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)")

}

Le journal de la console:

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

Nous pouvons améliorer les performances de la solution d’extension en simplifiant la règle. Les performances dépendent de la manière dont nous mettons en œuvre la règle. 

36
Duyen-Hoa

Typecasting avec une extension Nice String et vous êtes opérationnel

extension String {
var boolValue: Bool {
    return NSString(string: self).boolValue
}}
28
Nicolas Manzini

Utilisez ceci,

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

Comme déjà suggéré, je construirais une extension de String, énumérant uniquement les littéraux de chaîne que vous souhaitez convertir en true et false, tout en conservant un nil cas pour ce qui ne convertit pas (ou retournant false dans ce cas également? Votre choix! ). Au fait, vous ne voulez probablement pas que votre méthode soit sensible à la casse.

Par exemple:

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

Soyez prudent si vous utilisez un objet NSString et sa méthode boolValue(), car il renvoie true s'il rencontre "Y", "y", "T", "t" ou un chiffre 1-9 ( Voir docs ici ).

Par exemple:

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

Aucune autre réponse ne traite du potentiel des chaînes à majuscules ou à majuscules. Alors, pourquoi ne pas prendre la réponse de Kirsteins, associez-la à des propriétés magiques et shazam calculées:

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
        }
    }
}

L'utilisation serait:

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

Conclusion des réponses ci-dessus:

Vous pouvez utiliser une extension et une ligne simples.

Swift 3

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

Usage

 if (dictCardData.value(forKey: "isadmin") as! String).boolValueFromString() {
    // Stuff
}
3
Chetan Prajapati
 var st = "false"

 extension String {
   func toBool() -> Bool{
    if self == "false" {
        return false
    }else{
        return true
    }
}
}

 if st.toBool() == false {
     println("its ok")
 }
3
Muhammad Raza

Je préfère cette implémentation qui gère des chaînes facultatives et a une valeur par défaut de 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
        }
    }
}
1
doovers

J'ai pris la solution de Nicolas Manzini et l'ai légèrement modifiée. Je recommande d'utiliser l'opérateur de diffusion, car il est relié entre String et NSString. On ignore s'il s'agit d'un pont gratuit, mais il devrait offrir de meilleures performances que de créer aveuglément un nouvel objet. 

extension String {

    var boolValue: Bool {
        return (self as NSString).boolValue
    }
}
0
jangelsb

solution à une ligne pour chaîne optionnelle

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

J'ai refactored le code @Kirsteins en tant qu'initialiseur de Bool avec une valeur de chaîne

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
0
buxik

Si vous utilisez une fois, essayez ceci.

let str:String = "1"

var boo:Bool = str == "1" || str == "true" || str == "True" || str == "yes"
0
Paco_BB