root-11
root-11

Reputation: 1806

Is there a more pythonic way to convert a list of booleans to an integer?

I feel silly having to ask this question, but my memory evades me of better alternatives. Two appraoches that spring to mind:

First:

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

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

Second:

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

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

I feel that f1 is almost to clunky to be pythonic, and f2 is plainly too ugly as I'm jumping between multiple datatypes. Maybe its my age...?

Upvotes: 2

Views: 127

Answers (5)

Ryan1729
Ryan1729

Reputation: 1010

Just for contrast here's a way that you would do this if you were writing python as if you were writing something like c.

def f(l):
  output = 0
  for i in range(len(l)):
    output |= l[i] << i
  return output

Upvotes: 2

Martin
Martin

Reputation: 3385

Its little more rigid solution but its very computationally efficient

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

Upvotes: 0

snakecharmerb
snakecharmerb

Reputation: 55933

Using a left shift is slightly faster than raising to powers (at least on my machine). Using a bitwise operation encourages the reader of the code to think in terms of binary data.

>>> sum(v << i for i, v in enumerate([True, False, True]))
5

Upvotes: 4

Mykola Zotko
Mykola Zotko

Reputation: 17911

Using booleans in arithmetic operations (also lambda functions) is very pythonic:

lst = [True, False, True]

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

print(func(lst))
# 5

Upvotes: 1

Ofer Sadan
Ofer Sadan

Reputation: 11972

This is another hacky way I came up with:

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

Example:

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

Another identical example using map (more readable in my view):

def f1(v):
    return int(''.join(map(str, map(int, v))), 2)

Upvotes: 0

Related Questions