Comment convertir 'false' en 0 et 'true' en 1 en Python

119

Existe-t-il un moyen de convertir le truetype unicodeen 1 et le falsetype unicodeen 0 (en Python)?

Par exemple: x == 'true' and type(x) == unicode

Je voudrais x = 1

PS: je ne veux pas utiliser if- else.

PythonEnthusiast
la source

Réponses:

165

Utilisation int()sur un test booléen:

x = int(x == 'true')

int()transforme le booléen en 1ou 0. Notez que toute valeur non égale à 'true'entraînera le 0renvoi.

Martijn Pieters
la source
C'est une réponse merveilleuse sauf que tout ce qui n'est pas «vrai» serait interprété comme «0». Je ne sais pas si cela répondrait aux exigences des OP.
Abhijit
Bien que ce soit probablement ce que l'OP voulait, cela ne correspond pas exactement à la question posée pour python 2.7. Ils ont explicitement demandé qu'il fonctionne sur le type unicode et n'ont pas spécifié le comportement du type str.
wim
1
@wim En fait, la question ne mentionne jamais une version de python, encore moins le fait qu'il devrait s'agir de python2. 7 . Notez également qu'en python2 u'true' == 'true', la fonction se comporte correctement indépendamment du type d'entrée [entre stret unicode].
Bakuriu
Mais Bakuriu, c'est exactement ce que je veux dire, le "problème" est que u'true' == 'true'et que nous ne savons pas quel est le cas d'utilisation. Peut-être qu'ils veulent un comportement différent pour la situation où type(x) != unicode.
wim
1
@AlbertChen: non, car les tableaux numpy diffusent des comparaisons et ne produisent pas de valeur booléenne. Au lieu de cela, les comparaisons produisent un tableau de valeurs booléennes. Je ne suis pas sûr de ce que vous attendez d'une arrayvalue == 'true'comparaison, la question à laquelle j'ai répondu ici est spécifique à une valeur de chaîne (unicode).
Martijn Pieters
136

Si Best un tableau booléen, écrivez

B = B*1

(Un peu de code golfique.)

Snoop Catt
la source
1
Cette même chose fonctionne également pour les valeurs uniques. C'est bien!
user31415
2
Ne fonctionne pas pour moi dans Python 3 (le tableau reste booléen). Mais en utilisant des numpy.multiply(B,1)œuvres.
Alaa M.
cela fonctionne pour moi en python 3! et une telle solution brillante. oh my
alwaysaskingquestions
@Ourobours: Essayer de suivre votre suggestion n'a pas fonctionné pour moi.Bien que le sulotion original ait donné un bon résultat, des résultats fonctionnels ont B=map(int,B)renvoyé un objet de carte en python 3 pour moi.
Eulenfuchswiesel
1
@Eulenfuchswiesel Ceci est dû au fait que map renvoie un itérateur en Python3. Pour l'utiliser comme une liste, lancez-la sous forme de liste comme ceci: B = list (map (int, B))
Gigi Bayte 2
11

Vous pouvez utiliser x.astype('uint8')where xest votre tableau booléen.

shahar_m
la source
9

Voici une autre solution à votre problème:

def to_bool(s):
    return 1 - sum(map(ord, s)) % 2
    # return 1 - sum(s.encode('ascii')) % 2  # Alternative for Python 3

Cela fonctionne parce que la somme des codes ASCII de 'true'est 448, qui est paire, tandis que la somme des codes ASCII de 'false'est 523qui est impaire.


La chose amusante à propos de cette solution est que son résultat est assez aléatoire si l'entrée ne fait pas partie de 'true'ou 'false'. La moitié du temps, il reviendra 0, et l'autre moitié 1. La variante utilisant encodelèvera une erreur de codage si l'entrée n'est pas ASCII (augmentant ainsi l'indéfini-ness du comportement).


Sérieusement, je pense que la solution la plus lisible et la plus rapide consiste à utiliser un if:

def to_bool(s):
    return 1 if s == 'true' else 0

Voir quelques microbenchmarks:

In [14]: def most_readable(s):
    ...:     return 1 if s == 'true' else 0

In [15]: def int_cast(s):
    ...:     return int(s == 'true')

In [16]: def str2bool(s):
    ...:     try:
    ...:         return ['false', 'true'].index(s)
    ...:     except (ValueError, AttributeError):
    ...:         raise ValueError()

In [17]: def str2bool2(s):
    ...:     try:
    ...:         return ('false', 'true').index(s)
    ...:     except (ValueError, AttributeError):
    ...:         raise ValueError()

In [18]: def to_bool(s):
    ...:     return 1 - sum(s.encode('ascii')) % 2

In [19]: %timeit most_readable('true')
10000000 loops, best of 3: 112 ns per loop

In [20]: %timeit most_readable('false')
10000000 loops, best of 3: 109 ns per loop

In [21]: %timeit int_cast('true')
1000000 loops, best of 3: 259 ns per loop

In [22]: %timeit int_cast('false')
1000000 loops, best of 3: 262 ns per loop

In [23]: %timeit str2bool('true')
1000000 loops, best of 3: 343 ns per loop

In [24]: %timeit str2bool('false')
1000000 loops, best of 3: 325 ns per loop

In [25]: %timeit str2bool2('true')
1000000 loops, best of 3: 295 ns per loop

In [26]: %timeit str2bool2('false')
1000000 loops, best of 3: 277 ns per loop

In [27]: %timeit to_bool('true')
1000000 loops, best of 3: 607 ns per loop

In [28]: %timeit to_bool('false')
1000000 loops, best of 3: 612 ns per loop

Remarquez que la ifsolution est au moins 2,5 fois plus rapide que toutes les autres solutions. Cela n'a pas de sens de mettre comme une exigence d'éviter d'utiliser ifs sauf s'il s'agit d'une sorte de devoir (auquel cas vous n'auriez pas dû demander cela en premier lieu).

Bakuriu
la source
7

Si vous avez besoin d'une conversion à usage général à partir d'une chaîne qui en soi n'est pas un booléen, vous devriez mieux écrire une routine similaire à celle décrite ci-dessous. Conformément à l'esprit du typage du canard, je n'ai pas passé l'erreur en silence, mais je l'ai convertie en fonction du scénario actuel.

>>> def str2bool(st):
try:
    return ['false', 'true'].index(st.lower())
except (ValueError, AttributeError):
    raise ValueError('no Valid Conversion Possible')


>>> str2bool('garbaze')

Traceback (most recent call last):
  File "<pyshell#106>", line 1, in <module>
    str2bool('garbaze')
  File "<pyshell#105>", line 5, in str2bool
    raise TypeError('no Valid COnversion Possible')
TypeError: no Valid Conversion Possible
>>> str2bool('false')
0
>>> str2bool('True')
1
Abhijit
la source
2
Pourquoi un TypeError? Si la chaîne ne contient pas 'true'ou 'false'c'est une erreur de valeur . Si l'entrée n'est pas une chaîne, vous obtiendrez (99,99% des fois) an à la AttributeErrorplace, il est donc inutile de l'attraper ValueErroret de la re-soulever comme TypeError.
Bakuriu
@Bakuriu: Je suis d'accord. TypeError n'était en effet pas applicable ici.
Abhijit
@Bakuriu: juste par curiosité, pourriez-vous donner un exemple de indexlevée d'une AttributeError?
georg
@Bakuriu: Je pense que je plutôt parler de votre message ci - dessous: return ['false', 'true'].index(s) except (ValueError, AttributeError).
georg
@ thg435 Dans ce post, je viens de copier-coller et j'ai décidé de supprimer l' lower()appel car c'était la seule solution qui faisait ce calcul supplémentaire et il n'aurait pas été correct de l'inclure dans le micro-benchmark. Bien sûr, même cela try...exceptprend un peu de temps, mais la différence est petite si aucune exception n'est soulevée (comme 20nsmoins ou plus).
Bakuriu
0

booléen à int: x = (x == 'true') + 0

Maintenant, le x contient 1 x == 'true'sinon 0.

Remarque: x == 'true'retournera un booléen qui sera ensuite transtypé en int ayant une valeur (1 si la valeur booléenne est True sinon 0) lorsqu'il est ajouté avec 0.

MC Akash
la source
-2

seulement avec ceci:

const a = vrai; const b = faux;

console.log (+ a); // 1 console.log (+ b); // 0

Fernando Pascoal Gomes
la source