Come convertire "false" in 0 e "true" in 1 in Python


118

C'è un modo per convertire il truetipo unicodein 1 e il falsetipo unicodein 0 (in Python)?

Per esempio: x == 'true' and type(x) == unicode

Voglio x = 1

PS: non voglio usare if- else.

Risposte:


164

Utilizzare int()su un test booleano:

x = int(x == 'true')

int()trasforma il valore booleano in 1o 0. Notare che qualsiasi valore diverso da 'true'verrà 0restituito.


Questa è una risposta meravigliosa, tranne che tutto ciò che non è "vero" sarebbe interpretato come "0". Non sono sicuro che ciò soddisfi i requisiti dei PO.
Abhijit

Anche se probabilmente è quello che voleva l'OP, non corrisponde esattamente alla domanda posta per python 2.7. Hanno chiesto esplicitamente che funzionasse sul tipo unicode e non hanno specificato il comportamento del tipo str.
wim

1
@wim In realtà la domanda non menziona mai una versione di python, per non parlare del fatto che dovrebbe essere python2. 7 . Notare anche che in python2 u'true' == 'true'quindi la funzione si comporta correttamente indipendentemente dal tipo di input [tra stre unicode].
Bakuriu

Ma Bakuriu, questo è esattamente il mio punto, il "problema" è questo u'true' == 'true'e non sappiamo quale sia il caso d'uso. Forse vogliono un comportamento diverso per la situazione in cui type(x) != unicode.
wim

1
@ AlbertChen: no, perché gli array numpy trasmettono confronti e non producono un valore booleano. Invece, i confronti producono una matrice di valori booleani. Non sono sicuro di cosa ti aspetti da un arrayvalue == 'true'confronto, la domanda a cui ho risposto qui è specifica per un valore di stringa (unicode).
Martijn Pieters

136

Se Bè un array booleano, scrivi

B = B*1

(Un po 'di codice golfy.)


1
La stessa identica cosa funziona anche per valori singoli. È fantastico!
user31415

2
Non funziona per me in Python 3 (l'array rimane booleano). Ma usando le numpy.multiply(B,1)opere.
Alaa M.

questo funziona per me in Python 3! e una soluzione così brillante. oh mio
domande il

@ Ourobours: Cercare di seguire il tuo suggerimento non ha funzionato per me. Anche se il solotion originale ha dato un risultato piacevole e realizzabile, mi ha B=map(int,B)restituito un oggetto mappa in Python 3.
Eulenfuchswiesel

1
@Eulenfuchswiesel Questo perché map restituisce un iteratore in Python3. Per usarlo come una lista, lanciala come una lista in questo modo: B = list (map (int, B))
Gigi Bayte 2

11

Puoi usare x.astype('uint8')dov'è il xtuo array booleano.


9

Ecco un'altra soluzione al tuo problema:

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

Funziona perché la somma dei codici ASCII di 'true'IS 448, che è ancora, mentre la somma dei codici ASCII di 'false'IS 523che è strano.


La cosa divertente di questa soluzione è che il suo risultato è abbastanza casuale se l'input non è uno di 'true'o 'false'. La metà delle volte tornerà 0e l'altra metà 1. La variante utilizzando encodesolleverà un errore di codifica se l'input non è ASCII (aumentando così l'indefinizione del comportamento).


Seriamente, credo che la soluzione più leggibile e veloce sia usare un if:

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

Vedi alcuni microbenchmark:

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

Notare come la ifsoluzione sia almeno 2,5 volte più veloce di tutte le altre soluzioni. Non ha senso mettere come requisito per evitare di usare ifs tranne se si tratta di una sorta di compito a casa (nel qual caso non avresti dovuto chiederlo in primo luogo).


7

Se hai bisogno di una conversione generica da una stringa che di per sé non è un bool, dovresti scrivere una routine simile a quella illustrata di seguito. In linea con lo spirito della dattilografia, non ho superato l'errore in silenzio, ma l'ho convertito in modo appropriato per lo scenario corrente.

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

2
Perché un TypeError? Se la stringa non contiene 'true'o 'false'è un errore di valore . Se l'input non è una stringa, otterrai (99,99% delle volte) una stringa AttributeError, quindi è inutile recuperarla ValueErrore rilanciarla come TypeError.
Bakuriu

@ Bakuriu: sono d'accordo. TypeError non era effettivamente applicabile qui.
Abhijit

@ Bakuriu: solo per curiosità, potresti fare un esempio di indexinnalzamento di un AttributeError?
georg

@Bakuriu: Credo di essere stato piuttosto riferivo al tuo post qui sotto: return ['false', 'true'].index(s) except (ValueError, AttributeError).
georg

@ thg435 In quel post ho semplicemente copiato e ho deciso di rimuovere la lower()chiamata poiché questa era l'unica soluzione che faceva questo calcolo extra e non sarebbe stato corretto includerla nel micro-benchmark. Certo anche ci try...exceptvuole un po 'di tempo, ma la differenza è piccola se non viene sollevata alcuna eccezione (come 20nsmeno o giù di lì).
Bakuriu

0

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

Ora la x contiene 1 se x == 'true'altrimenti 0.

Nota: x == 'true'restituirà bool che verrà quindi convertito in int con valore (1 se il valore bool è True altrimenti 0) quando aggiunto con 0.


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.