Como converter 'falso' em 0 e 'verdadeiro' em 1 em Python

118

Existe uma maneira de converter truedo tipo unicodeem 1 e falsedo tipo unicodeem 0 (em Python)?

Por exemplo: x == 'true' and type(x) == unicode

eu quero x = 1

PS: Não quero usar if- else.

PythonEnthusiast
fonte

Respostas:

164

Use int()em um teste booleano:

x = int(x == 'true')

int()transforma o booleano em 1ou 0. Note-se que qualquer valor não igual a 'true'irá resultar em 0que estão sendo devolvidos.

Martijn Pieters
fonte
Esta é uma resposta maravilhosa, exceto que tudo sem 'verdadeiro' seria interpretado como '0'. Não tenho certeza se isso atenderia aos requisitos de OPs.
Abhijit
Embora seja provavelmente o que o OP queria, não corresponde exatamente à pergunta feita para o python 2.7. Eles pediram explicitamente para que funcionasse no tipo Unicode e não especificaram o comportamento do tipo str.
wim
1
@wim Na verdade, a pergunta nunca menciona uma versão python, muito menos o fato de que deveria ser python2. 7 . Observe também que em python2 u'true' == 'true', a função se comporta corretamente independentemente do tipo de entrada [entre stre unicode].
Bakuriu
Mas Bakuriu, esse é exatamente o meu ponto, o "problema" é esse u'true' == 'true'e não sabemos qual é o caso de uso. Talvez eles queiram um comportamento diferente para a situação em que type(x) != unicode.
wim
1
@AlbertChen: não, porque matrizes numpy transmitem comparações e não produzem um valor booleano. Em vez disso, as comparações produzem uma matriz de valores booleanos. Não tenho certeza do que você espera de uma arrayvalue == 'true'comparação, a pergunta que respondi aqui é específica para um valor de string (Unicode).
Martijn Pieters
136

Se Bfor uma matriz booleana, escreva

B = B*1

(Um código de bits)

Chipotle
fonte
1
Exatamente a mesma coisa também funciona para valores únicos. Isso é ótimo!
user31415
2
Não funciona para mim em Python 3 (array permanece booleano). Mas usando numpy.multiply(B,1)obras.
Alaa M.
isso funciona para mim no python 3! e essa solução brilhante. oh meu
fazendo perguntas
@Ourobours: Tentar seguir sua sugestão não funcionou para mim. Enquanto o sulotion original deu um bom resultado, os resultados viáveis B=map(int,B)retornaram um objeto de mapa em python 3 para mim.
Eulenfuchswiesel
1
@Eulenfuchswiesel Isso ocorre porque map retorna um iterador em Python3. Para usá-lo como uma lista, lance-o como uma lista assim: B = lista (map (int, B))
Gigi Bayte 2 de
11

Você pode usar x.astype('uint8')where xestá o seu array booleano.

shahar_m
fonte
9

Aqui está outra solução para o seu problema:

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

Ele funciona porque a soma dos códigos ASCII de 'true'é 448, o que é ainda, enquanto a soma dos códigos ASCII de 'false'é 523que é estranho.


O engraçado sobre esta solução é que seu resultado é bastante aleatório se a entrada não for um 'true'ou 'false'. Metade das vezes ele vai voltar 0e a outra metade 1. A variante usando encodegerará um erro de codificação se a entrada não for ASCII (aumentando assim a indefinição do comportamento).


Sério, acredito que a solução mais legível e rápida é usar um if:

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

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

Observe como a ifsolução é pelo menos 2,5x vezes mais rápido do que todos as outras soluções. Ele não faz sentido colocar como um requisito para evitar o uso de ifs exceto se isso é algum tipo de lição de casa (caso em que você não deveria ter perguntado isso em primeiro lugar).

Bakuriu
fonte
7

Se você precisar de uma conversão de propósito geral de uma string que per se não é um bool, é melhor escrever uma rotina semelhante à descrita abaixo. Mantendo o espírito da digitação de pato, não passei o erro silenciosamente, mas o converti como apropriado para o cenário atual.

>>> 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
fonte
2
Por que um TypeError? Se a string não contém 'true'ou 'false'é um erro de valor . Se a entrada não for uma string, você obterá (99,99% das vezes) um an AttributeError, portanto, é inútil capturá ValueError-la e aumentá-la novamente como TypeError.
Bakuriu
@Bakuriu: Eu concordo. TypeError de fato não era aplicável aqui.
Abhijit
@Bakuriu: só por curiosidade, você poderia dar um exemplo de como indexgerar um AttributeError?
georg
@Bakuriu: Eu acho que eu estava em vez referindo-se a seu post abaixo: return ['false', 'true'].index(s) except (ValueError, AttributeError).
georg
@ thg435 Naquela postagem, apenas copiei e colei e decidi remover a lower()chamada, pois essa era a única solução que fazia esse cálculo extra e não seria correto incluí-la no micro-benchmark. Claro, mesmo isso try...exceptleva um pouco de tempo, mas a diferença é pequena se nenhuma exceção for levantada (como 20nsmenos ou menos).
Bakuriu
0

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

Agora, o x contém 1 x == 'true'senão 0.

Nota: x == 'true'retornará bool que então será convertido para int com valor (1 se o valor bool for True, caso contrário 0) quando adicionado com 0.

MC Akash
fonte
-2

apenas com isso:

const a = verdadeiro; const b = falso;

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

Fernando Pascoal Gomes
fonte