Есть ли более питонный способ преобразования списка логических значений в целое число? - PullRequest
2 голосов
/ 11 ноября 2019

Мне глупо задавать этот вопрос, но моя память уклоняется от лучших альтернатив. На ум приходят два аппроксима:

Первый:

def f1(v):
    return sum(2**i for i,va in enumerate(v) if va)

>>> f1([True, False, True])
5

Второй:

def f2(v):
    return int('0b' + "".join(str(int(va)) for va in v),2)

>>> f2([True, False, True])
5

Я чувствую, что f1 почти неуклюж, чтобы быть питоническим, а f2 - этоявно слишком некрасиво, когда я прыгаю между несколькими типами данных. Может быть, это мой возраст ...?

Ответы [ 5 ]

4 голосов
/ 11 ноября 2019

Использование левого смещения немного быстрее, чем повышение до мощности (по крайней мере, на моей машине). Использование побитовой операции побуждает читателя кода мыслить в терминах двоичных данных.

>>> sum(v << i for i, v in enumerate([True, False, True]))
5
1 голос
/ 11 ноября 2019

Для контраста, вот способ, которым вы бы сделали это, если бы вы писали на python, как если бы вы писали что-то вроде c.

def f(l):
  output = 0
  for i in range(len(l)):
    output |= l[i] << i
  return output
1 голос
/ 11 ноября 2019

Использование логических выражений в арифметических операциях (также лямбда-функции) очень питонно:

lst = [True, False, True]

func = lambda x: sum(2 ** num * i for num, i in enumerate(x))

print(func(lst))
# 5
0 голосов
/ 11 ноября 2019

Это немного более жесткое решение, но очень вычислительно эффективный

>>> import numpy as np

>>> predefined_bytes = 2**(np.arange(32))
>>> predefined_bytes
array([         1,          2,          4,          8,         16,
               32,         64,        128,        256,        512,
             1024,       2048,       4096,       8192,      16384,
            32768,      65536,     131072,     262144,     524288,
          1048576,    2097152,    4194304,    8388608,   16777216,
         33554432,   67108864,  134217728,  268435456,  536870912,
       1073741824, 2147483648])


def binary2decimal(bits,predefined_bytes):
    bits = np.array(bits)
    return np.sum(bits*predefined_bytes[:bits.shape[0]])

>>> binary2decimal([1,1,1,1,1,1,1,1],predefined_bytes)
255
0 голосов
/ 11 ноября 2019

Это еще один хакерский способ, которым я придумал:

def f1(v):
    return int(''.join(str(int(b)) for b in v), 2)

Пример:

>>> def f1(v):
...     return int(''.join(str(int(b)) for b in v), 2)
...
>>> f1([True, False, True])
5
>>>

Еще один идентичный пример с использованием map (более читабелен, на мой взгляд):

def f1(v):
    return int(''.join(map(str, map(int, v))), 2)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...