So konvertieren Sie in Python 'false' in 0 und 'true' in 1

118

Gibt es eine Möglichkeit, truevom Typ unicodein 1 und falsevom Typ zu konvertieren ?unicode in 0 (in Python) ?

Beispielsweise: x == 'true' and type(x) == unicode

Ich will x = 1

PS: Ich möchte nicht verwenden if- else.

PythonEnthusiast
quelle

Antworten:

163

Verwendung int()bei einem Booleschen Test:

x = int(x == 'true')

int()verwandelt den Booleschen Wert in 1oder 0. Beachten Sie, dass jeder Wert nicht zu gleichen 'true'führt zu 0zurückgegeben werden.

Martijn Pieters
quelle
Dies ist eine wunderbare Antwort, außer dass alles ohne 'wahr' als '0' interpretiert wird. Ich bin mir nicht sicher, ob dies den Anforderungen des OP entspricht.
Abhijit
Obwohl es wahrscheinlich das ist, was das OP wollte, stimmt es nicht genau mit der Frage überein, die für Python 2.7 gestellt wurde. Sie haben ausdrücklich darum gebeten, dass es mit Typ-Unicode funktioniert, und das Verhalten für Typ nicht angegeben str.
wim
1
@wim Eigentlich erwähnt die Frage niemals eine Python-Version, geschweige denn die Tatsache, dass es Python2 sein sollte. 7 . Beachten Sie auch, u'true' == 'true'dass sich die Funktion in Python2 unabhängig vom Eingabetyp [zwischen strund unicode] korrekt verhält .
Bakuriu
Aber Bakuriu, das ist genau mein Punkt, das "Problem" ist das u'true' == 'true'und dass wir nicht wissen, was der Anwendungsfall ist. Vielleicht wollen sie ein anderes Verhalten für die Situation, in der type(x) != unicode.
wim
1
@AlbertChen: Nein, da Numpy-Arrays Vergleiche senden und keinen booleschen Wert erzeugen. Stattdessen erzeugen Vergleiche ein Array von Booleschen Werten. Ich bin mir nicht sicher, was Sie von einem arrayvalue == 'true'Vergleich erwarten . Die Frage, die ich hier beantwortet habe, ist spezifisch für einen Zeichenfolgenwert (Unicode).
Martijn Pieters
136

Wenn Bes sich um ein boolesches Array handelt, schreiben Sie

B = B*1

(Ein bisschen Code Golf.)

Chipotle
quelle
1
Genau das Gleiche gilt auch für Einzelwerte. Das ist toll!
user31415
2
Funktioniert bei Python 3 nicht (Array bleibt boolesch). Aber mit numpy.multiply(B,1)Arbeiten.
Alaa M.
Das funktioniert bei mir in Python 3! und solch eine brillante Lösung. oh mein
fragende Fragen
@Ourobours: Der Versuch, Ihrem Vorschlag zu folgen, hat bei mir nicht funktioniert. Während die ursprüngliche Sulotion zu schönen, praktikablen Ergebnissen B=map(int,B)führte, wurde für mich ein Kartenobjekt in Python 3 zurückgegeben.
Eulenfuchswiesel
1
@Eulenfuchswiesel Dies liegt daran, dass map in Python3 einen Iterator zurückgibt. Um es als Liste zu verwenden, werfen Sie es wie
folgt in
11

Sie können verwenden, x.astype('uint8')wo xsich Ihr Boolesches Array befindet.

shahar_m
quelle
9

Hier ist eine weitere Lösung für Ihr Problem:

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

Es funktioniert , weil die Summe des ASCII - Codes von 'true'heißt 448, die selbst ist, während die Summe des ASCII - Codes von 'false'heißt , 523die ungerade ist.


Das Lustige an dieser Lösung ist, dass das Ergebnis ziemlich zufällig ist, wenn die Eingabe nicht eine von 'true'oder ist 'false'. Die Hälfte der Zeit wird es zurückkehren 0und die andere Hälfte 1. Die verwendete Variante encodelöst einen Codierungsfehler aus, wenn die Eingabe nicht ASCII ist (wodurch die Undefiniertheit des Verhaltens erhöht wird).


Im Ernst, ich glaube, die am besten lesbare und schnellere Lösung ist die Verwendung von if:

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

Siehe einige Mikrobenchmarks:

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

Beachten Sie, dass die ifLösung mindestens 2,5- mal schneller ist als alle anderen Lösungen. Es ist nicht sinnvoll, ifs als Voraussetzung für die Vermeidung der Verwendung von s anzugeben, es sei denn, dies ist eine Art Hausaufgabe (in diesem Fall hätten Sie dies gar nicht erst fragen sollen).

Bakuriu
quelle
7

Wenn Sie eine Allzweckkonvertierung von einer Zeichenfolge benötigen, die per se kein Bool ist, sollten Sie eine Routine schreiben, die der unten abgebildeten ähnlich ist. In Übereinstimmung mit dem Geist der Ententypisierung habe ich den Fehler nicht stillschweigend übergeben, sondern ihn entsprechend dem aktuellen Szenario konvertiert.

>>> 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
quelle
2
Warum ein TypeError? Wenn die Zeichenfolge nicht enthalten 'true'oder 'false'es ist ein Wert Fehler. Wenn es sich bei der Eingabe nicht um eine Zeichenfolge handelt, erhalten Sie (in 99,99% der Fälle) AttributeErrorstattdessen eine Zeichenfolge. Daher ist es sinnlos, sie abzufangen ValueErrorund erneut zu erhöhen TypeError.
Bakuriu
@ Bakuriu: Ich stimme zu. TypeError war hier tatsächlich nicht anwendbar.
Abhijit
@ Bakuriu: Könnten Sie aus Neugier ein Beispiel für indexdas Auslösen eines AttributeError geben?
Georg
@ Bakuriu: Ich denke, ich habe mich eher auf deinen Beitrag unten bezogen : return ['false', 'true'].index(s) except (ValueError, AttributeError).
Georg
@ thg435 In diesem Beitrag habe ich nur kopiert und beschlossen, den lower()Anruf zu entfernen , da dies die einzige Lösung war, die diese zusätzliche Berechnung durchgeführt hat, und es nicht richtig gewesen wäre, sie in den Mikro-Benchmark aufzunehmen. Sicher, auch das try...exceptdauert ein bisschen, aber der Unterschied ist gering, wenn keine Ausnahme gemacht wird (wie 20nsweniger oder so).
Bakuriu
0

bool to int: x = (x == 'true') + 0

Jetzt enthält das x 1 if x == 'true' sonst 0.

Hinweis: x == 'true'Gibt bool zurück, das dann mit dem Wert int (1, wenn der bool-Wert True else 0 ist) typisiert wird, wenn es mit 0 hinzugefügt wird.

MC Akash
quelle
-2

nur damit:

const a = true; const b = false;

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

Fernando Pascoal Gomes
quelle