Reputation: 2178
Suppose I have a list:
lst = [0, 1, 0, 0]
How can I make python interpret this list as a binary number 0100 so that 2*(0100)
gives me 01000
?
The only way that I can think of is to first make a function that converts the "binary" elements to corresponding integers(to base 10) and then use bin() function..
Is there a better way?
Upvotes: 10
Views: 32473
Reputation: 11
Because I have a project atm, where I need to convert an black-white image to a byte-array and send it via TCP, I searched for a "as fast as possible" solution.
So I took some solutions from here, added some I thought of and let run some speed tests.
I thought sharing this would maybe be helpful...
import timeit
BIN_LIST = [1, 0, 1, 0, 1, 0, 1, 0]
TIMEIT_ITERATIONS = 10000
def f_01(l):
return bin(int(''.join(map(str, l)), 2) << 1)
def f_02(l):
num = 0
for b in l:
num = 2 * num + b
return num
def f_03(l):
return int(''.join(str(i) for i in l), 2)
def f_04(l):
return sum(c << i for i, c in enumerate(l))
def f_05(l):
return bin(int(''.join(map(str, l)))<<1)
"""
From here on it's just stuff I tried out for myself
"""
def f_06(l):
res = 0
for i, v in enumerate(l[::-1]):
res += v << i
return res
def f_07(l):
res = 0
for i, v in enumerate(l):
res += v << 7 - i
return res
def f_08(l):
"""
Well, why not
"""
return int(f"{l[0]}{l[1]}{l[2]}{l[3]}{l[4]}{l[5]}{l[6]}{l[7]}", base=2)
def f_09(l):
"""
bear with me
"""
return int("{}{}{}{}{}{}{}{}".format(*l), base=2)
def f_10(l, i=7, r=0):
"""
let's try a little recursion
"""
if i >= 0:
return f_10(l, i-1, r + (l[i] << 7 - i))
else:
return r
"""
Last try with C code
"""
from cffi import FFI
ffi = FFI()
ffi.set_source("c_make_bin",
"""
int f_11(unsigned char l[8])
{
int res = 0 ;
for (int i=0; i<8; i+=1)
{
res = 2 * res + l[i] ;
}
return res ;
}
""")
ffi.cdef("""int f_11(unsigned char[8]) ;""")
ffi.compile()
from c_make_bin import lib
p = ffi.new("unsigned char[]", BIN_LIST)
"""
And well, look to the results -> C Code is .. and stays the fastest
"""
t_01 = timeit.Timer(lambda: f_01(BIN_LIST))
t_02 = timeit.Timer(lambda: f_02(BIN_LIST))
t_03 = timeit.Timer(lambda: f_03(BIN_LIST))
t_04 = timeit.Timer(lambda: f_04(BIN_LIST))
t_05 = timeit.Timer(lambda: f_05(BIN_LIST))
t_06 = timeit.Timer(lambda: f_06(BIN_LIST))
t_07 = timeit.Timer(lambda: f_07(BIN_LIST))
t_08 = timeit.Timer(lambda: f_08(BIN_LIST))
t_09 = timeit.Timer(lambda: f_09(BIN_LIST))
t_10 = timeit.Timer(lambda: f_10(BIN_LIST))
t_11 = timeit.Timer(lambda: lib.f_11(p))
result_01 = t_01.timeit(TIMEIT_ITERATIONS)
result_02 = t_02.timeit(TIMEIT_ITERATIONS)
result_03 = t_03.timeit(TIMEIT_ITERATIONS)
result_04 = t_04.timeit(TIMEIT_ITERATIONS)
result_05 = t_05.timeit(TIMEIT_ITERATIONS)
result_06 = t_06.timeit(TIMEIT_ITERATIONS)
result_07 = t_07.timeit(TIMEIT_ITERATIONS)
result_08 = t_08.timeit(TIMEIT_ITERATIONS)
result_09 = t_09.timeit(TIMEIT_ITERATIONS)
result_10 = t_10.timeit(TIMEIT_ITERATIONS)
result_11 = t_11.timeit(TIMEIT_ITERATIONS)
print("\n--- Test Results ---\n\n")
print("Function 01:", round(result_01, 5), "s", " --- join, map")
print("Function 02:", round(result_02, 5), "s", " --- simple for")
print("Function 03:", round(result_03, 5), "s", " --- join, tuple comprehension")
print("Function 04:", round(result_04, 5), "s", " --- shift, enumerate")
print("Function 05:", round(result_05, 5), "s", " --- join, map [2]")
print("Function 06:", round(result_06, 5), "s", " --- shift, reverse, enumerate in for")
print("Function 07:", round(result_07, 5), "s", " --- shift, enumerate in for")
print("Function 08:", round(result_08, 5), "s", " --- fstring")
print("Function 09:", round(result_09, 5), "s", " --- "".format")
print("Function 10:", round(result_10, 5), "s", " --- recursive")
print("Function 11:", round(result_11, 5), "s", " --- compiled C code")
Terminal Output:
--- Test Results ---
Function 01: 0.02623 s --- join, map
Function 02: 0.00718 s --- simple for
Function 03: 0.03302 s --- join, tuple comprehension
Function 04: 0.01773 s --- shift, enumerate
Function 05: 0.02497 s --- join, map [2]
Function 06: 0.0141 s --- shift, reverse, enumerate in for
Function 07: 0.01427 s --- shift, enumerate in for
Function 08: 0.01479 s --- fstring
Function 09: 0.01344 s --- .format
Function 10: 0.02424 s --- recursive
Function 11: 0.0047 s --- compiled C code
Upvotes: 1
Reputation: 149
lst = [4,5,7,1,2]
bin(int(''.join(map(str, lst)))<<1)
o/p:- '0b10110010100100000'
>>> lst =[4,5,7,1,2]
>>> bin(int(''.join(map(str, lst)))<<1)
o/p:- '0b10110010100100000'
Upvotes: 0
Reputation: 21
slightly different approach with comprehension (i hope it will be helpful for someone)
arr =[192, 168, 0, 1]
arr_s = [bin(i)[2:].zfill(8) for i in ar]
num = int(''.join(arr_s), 2)
same, but reverse order (and also one-liner suitable for lambdas )
arr = [24, 85, 0]
num = int(''.join( [bin(i)[2:].zfill(8) for i in arr[::-1]] ), 2)
using bit-wise and reduce:
reduce ((lambda x,y: (x<<8)|y), arr[::-1])
Upvotes: 1
Reputation: 9473
The accepted answer, joining a string, is not the fastest.
import random
lst = [int(i < 50) for i in random.choices(range(100), k=100)]
def join_chars(digits):
return int(''.join(str(i) for i in digits), 2)
%timeit join_chars(lst)
13.1 µs ± 450 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
def sum_digits(digits):
return sum(c << i for i, c in enumerate(digits))
%timeit sum_digits(lst)
5.99 µs ± 65.5 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
So bit-banging sum_digits()
comes first by a factor of x2!
Upvotes: 6
Reputation: 75
You can use this code for concatenating the list elements:
x=[0, 1, 0, 0]
b=''.join(map(str,x))
print(b)
Output:
C:\python\prog>python trying.py
0100
Upvotes: 0
Reputation: 17247
This is not a fancy one-liner, but simple and fast.
lst = [0,1,1,0]
num = 0
for b in lst:
num = 2 * num + b
print(num) # 6
Upvotes: 5
Reputation: 61225
You can use bitwise operators like this:
>>> lst = [0, 1, 0, 0]
>>> bin(int(''.join(map(str, lst)), 2) << 1)
'0b1000'
Upvotes: 6
Reputation: 1
You can try:
l = [0, 0, 1, 0]
num = int(''.join(str(x) for x in l), base=2)
Upvotes: -2