Як перетворити "false" на 0 і "true" на 1 в Python


118

Чи існує спосіб перетворення trueтипу unicodeв 1 і falseтипу unicodeв 0 (в Python)?

Наприклад: x == 'true' and type(x) == unicode

я хочу x = 1

PS: Я не хочу використовувати if- else.

Відповіді:


164

Використовувати int()на булевому тесті:

x = int(x == 'true')

int()перетворює булеву в 1або 0. Зауважте, що будь-яке значення, яке не дорівнює 'true', призведе до 0повернення.


Це чудова відповідь, за винятком того, що все, що говорить про "правду", трактується як "0". Не впевнений, чи відповідає це вимогам ОП.
Abhijit

Хоча це, мабуть, те, що хотіла ОП, воно не відповідає точно тому питанню, як просили python 2.7. Вони явно попросили, щоб він працював на тип unicode, і не вказали поведінку для типу str.
wim

1
@wim Насправді питання ніколи не згадує версії python, не кажучи вже про те, що він повинен бути python2. 7 . Також зауважте, що в python2 u'true' == 'true'така функція поводиться правильно незалежно від типу введення [між strта unicode].
Бакуріу

Але Бакуріу, це якраз моя думка, "проблема" полягає в тому, u'true' == 'true'що ми не знаємо, що таке використання. Можливо, вони хочуть іншої поведінки для ситуації, де type(x) != unicode.
Вім

1
@AlbertChen: ні, тому що numpy масиви транслюють порівняння і не дають булевого значення. Натомість порівняння створюють масив булевих значень. Я не впевнений, що ви очікуєте від arrayvalue == 'true'порівняння, питання, на яке я тут відповів, стосується значення рядка (unicode).
Martijn Pieters

136

Якщо Bбулевий масив, пишіть

B = B*1

(Трохи код гольф.)


1
Це саме те саме працює і для одиничних значень. Це чудово!
користувач31415

2
Не працює для мене в Python 3 (масив залишається логічним). Але використовуючи numpy.multiply(B,1)твори.
Алаа М.

це працює для мене в python 3! і таке геніальне рішення. о мій
завждизапитання

@Ourobours: Спроба дотримуватися вашої пропозиції не спрацювала B=map(int,B)для мене. Хоча оригінальне видання дало приємні, працездатні результати, повернуло для мене об'єкт карти в python 3.
Eulenfuchswiesel

1
@Eulenfuchswiesel Це тому, що карта повертає ітератор в Python3. Щоб використовувати його як список, подайте його як такий список: B = список (карта (int, B))
Gigi Bayte 2

11

Ви можете використовувати x.astype('uint8')там, де xваш булевий масив.


9

Ось ще одне рішення вашої проблеми:

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

Він працює тому, що сума кодів ASCII 'true'є 448, яка є парною, тоді як сума кодів ASCII 'false', 523яка непарна.


Найсмішніше в цьому рішенні є те , що його результатом є досить випадковим , якщо вхід НЕ один з 'true'чи 'false'. Половину часу вона повернеться 0, а іншу половину 1. Варіант використання encodeпризведе до помилки кодування, якщо вхід не ASCII (таким чином збільшується невизначеність поведінки).


Серйозно, я вважаю, що найчитабельнішим та швидшим рішенням є використання if:

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

Ознайомтеся з деякими мікро-орієнтирами:

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

Зауважте, як ifрішення принаймні в 2,5 рази швидше, ніж усі інші рішення. Це НЕ має сенсу ставити як вимога , щоб уникнути використання ifS , за винятком , якщо це якесь - то домашній (в цьому випадку ви не повинні були запитати це в першу чергу).


7

Якщо вам потрібна конверсія загального призначення з рядка, яка сама по собі не є булом, вам краще написати процедуру, подібну до зображеної нижче. Відповідно до духу набору тексту качки, я не мовчки передавав помилку, а перетворював її як відповідну для поточного сценарію.

>>> 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
Чому а TypeError? Якщо рядок не містить 'true'або 'false'це помилка значення . Якщо введення не є рядком, ви отримаєте (99,99% разів) AttributeErrorнатомість, отже, марно його ловити ValueErrorта повторно піднімати як TypeError.
Бакуріу

@Bakuriu: Я згоден. Тут не було застосовано TypeError.
Абхіджіт

@Bakuriu: просто з цікавості, чи можете ви навести приклад indexпідвищення AttributeError?
georg

@Bakuriu: Я припускаю , що я швидше з посиланням на свій пост нижче: return ['false', 'true'].index(s) except (ValueError, AttributeError).
georg

@ thg435 У цій публікації я просто скопіював копію і вирішив видалити lower()виклик, оскільки це було єдиним рішенням, яке зробило це додаткове обчислення, і не було б коректним включити його в мікропоказник. Впевнені, що навіть try...exceptпотрібно небагато часу, але різниця невелика, якщо не робиться жодного винятку (як-небудь 20nsменше).
Бакуріу

0

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

Тепер x містить 1, якщо x == 'true'інше 0.

Примітка: x == 'true'поверне bool, який потім буде введено до int зі значенням (1, якщо значення bool є True else 0), додавши 0.


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.