Jak przekonwertować „false” na 0 i „true” na 1 w Pythonie

120

Czy istnieje sposób na przekonwertowanie truetypu unicodena 1 i falsetypu unicodena 0 (w Pythonie)?

Na przykład: x == 'true' and type(x) == unicode

chcę x = 1

PS: nie chcę używać if- else.

PythonEnthusiast
źródło

Odpowiedzi:

165

Użyj int()w teście boolowskim:

x = int(x == 'true')

int()zamienia wartość logiczną na 1lub 0. Zwróć uwagę, że każda wartość, która nie jest równa, 'true'spowoduje 0zwrócenie.

Martijn Pieters
źródło
To wspaniała odpowiedź, z tym wyjątkiem, że wszystko bez „prawdy” byłoby interpretowane jako „0”. Nie jestem pewien, czy spełniłoby to wymagania PO.
Abhijit
Chociaż prawdopodobnie tego chciał OP, nie odpowiada dokładnie pytaniu zadanemu w Pythonie 2.7. Wyraźnie poprosili, aby działał na typie Unicode i nie określili zachowania dla typu str.
wim
1
@wim Właściwie to pytanie nigdy nie wspomina o wersjach Pythona, nie mówiąc już o fakcie, że powinno to być python2. 7 . Zauważ również, że w pythonie2 u'true' == 'true'funkcja zachowuje się poprawnie niezależnie od typu danych wejściowych [pomiędzy stri unicode].
Bakuriu,
Ale Bakuriu, dokładnie o to mi chodzi, „problem” polega na tym u'true' == 'true', że nie wiemy, jaki jest przypadek użycia. Może chcą innego zachowania w sytuacji, w której type(x) != unicode.
wim
1
@AlbertChen: nie, ponieważ tablice numpy transmitują porównania i nie generują wartości logicznej. Zamiast tego porównania tworzą tablicę wartości logicznych. Nie jestem pewien, czego oczekujesz od arrayvalue == 'true'porównania, pytanie, na które tutaj odpowiedziałem, dotyczy wartości string (Unicode).
Martijn Pieters
137

Jeśli Bjest tablicą boolowską, napisz

B = B*1

(Trochę kodu golfowego.)

Snoop Catt
źródło
1
Dokładnie to samo działa również dla pojedynczych wartości. To jest świetne!
user31415
2
Nie działa dla mnie w Pythonie 3 (tablica pozostaje logiczna). Ale używanie numpy.multiply(B,1)działa.
Alaa M.
to działa dla mnie w Pythonie 3! i takie genialne rozwiązanie. oh my
alwaysaskingquestions
@Ourobours: Próba podążania za twoją sugestią nie zadziałała, podczas gdy oryginalne sulotion dało fajne, działające wyniki, B=map(int,B)zwróciło mi obiekt mapy w pythonie 3.
Eulenfuchswiesel
1
@Eulenfuchswiesel Dzieje się tak, ponieważ mapa zwraca iterator w Pythonie3. Aby użyć go jako listy, prześlij go jako listę w następujący sposób: B = lista (mapa (int, B))
Gigi Bayte 2
11

Możesz użyć x.astype('uint8')gdzie xjest twoja tablica logiczna.

shahar_m
źródło
9

Oto jeszcze jedno rozwiązanie Twojego problemu:

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

To działa, ponieważ suma kodów ASCII 'true'Is 448, który jest nawet, gdy suma kodów ASCII 'false'Is 523co jest dziwne.


Zabawne w tym rozwiązaniu jest to, że jego wynik jest dość losowy, jeśli wejście nie jest jednym z 'true'lub 'false'. W połowie czasu wróci 0, a drugą połowę 1. Wariant wykorzystujący encodespowoduje zgłoszenie błędu kodowania, jeśli dane wejściowe nie są w formacie ASCII (zwiększając w ten sposób nieokreśloność zachowania).


Poważnie, uważam, że najbardziej czytelnym i szybszym rozwiązaniem jest użycie if:

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

Zobacz kilka mikroznaków:

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

Zwróć uwagę, że ifrozwiązanie jest co najmniej 2,5 razy szybsze niż wszystkie inne rozwiązania. To nie nie ma sensu, aby umieścić jako wymóg, aby unikać ifs wyjątkiem sytuacji, gdy jest to jakiś rodzaj pracy domowej (w takim przypadku nie należy prosić to w pierwszej kolejności).

Bakuriu
źródło
7

Jeśli potrzebujesz konwersji ogólnego przeznaczenia z łańcucha, który sam w sobie nie jest wartością logiczną, lepiej napisać procedurę podobną do przedstawionej poniżej. Zgodnie z duchem pisania kaczkami nie przeszedłem po cichu błędu, ale przekonwertowałem go tak, aby był odpowiedni dla obecnego scenariusza.

>>> 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
źródło
2
Dlaczego TypeError? Jeśli ciąg nie zawiera 'true'lub 'false'jest to błąd wartości . Jeśli dane wejściowe nie są ciągami znaków, AttributeErrorzamiast nich (w 99,99% przypadków) otrzymasz an , stąd bezcelowe jest łapanie ValueErrori ponowne podnoszenie jako TypeError.
Bakuriu
@Bakuriu: Zgadzam się. TypeError rzeczywiście nie miał tutaj zastosowania.
Abhijit
@Bakuriu: czy mógłbyś podać przykład indexpodniesienia błędu AttributeError, tak z ciekawości ?
georg
@Bakuriu: Chyba raczej odnosząc się do postu poniżej: return ['false', 'true'].index(s) except (ValueError, AttributeError).
georg
@ thg435 W tym poście po prostu skopiowałem i wkleiłem i zdecydowałem usunąć lower()wywołanie, ponieważ było to jedyne rozwiązanie, które wykonało te dodatkowe obliczenia i nie byłoby poprawne włączenie go do mikro-testu. Jasne, nawet try...exceptzajmuje to trochę czasu, ale różnica jest niewielka, jeśli nie zostanie zgłoszony żaden wyjątek ( 20nsmniej więcej).
Bakuriu
0

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

Teraz x zawiera 1, jeśli w przeciwnym razie x == 'true'0.

Uwaga: x == 'true'zwróci wartość bool, która zostanie następnie wpisana do typu int o wartości (1, jeśli wartość bool to True else 0) po dodaniu z 0.

MC Akash
źródło
-2

tylko z tym:

const a = true; const b = false;

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

Fernando Pascoal Gomes
źródło