I decided to create a script to trial 4 different methods of doing this task.
import time
trials = range(1000000)
list1 = [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0]
list0 = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
listmix = [1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0]
def test1(l):
start = time.time()
for trial in trials:
tot = 0
n = 1
for i in reversed(l):
if i:
tot += 2**n
n += 1
print 'Time taken:', str(time.time() - start)
def test2(l):
start = time.time()
for trial in trials:
int("".join(map(str, l)),2)
print 'Time taken:', str(time.time() - start)
def test3(l):
start = time.time()
for trial in trials:
sum(x << i for i, x in enumerate(reversed(l)))
print 'Time taken:', str(time.time() - start)
def test4(l):
start = time.time()
for trial in trials:
int("".join([str(i) for i in l]),2)
print 'Time taken:', str(time.time() - start)
test1(list1)
test2(list1)
test3(list1)
test4(list1)
print '.'
test1(list0)
test2(list0)
test3(list0)
test4(list0)
print '.'
test1(listmix)
test2(listmix)
test3(listmix)
test4(listmix)
My results:
Time taken: 7.14670491219
Time taken: 5.4076821804
Time taken: 4.7349550724
Time taken: 7.24234819412
.
Time taken: 2.29213285446
Time taken: 5.38784003258
Time taken: 4.70707392693
Time taken: 7.27936697006
.
Time taken: 4.78960323334
Time taken: 5.36612486839
Time taken: 4.70103287697
Time taken: 7.22436404228
Conclusion: @goncalopp's solution is probably the best one. It is consistently fast. On the other hand, if you're likely to have more zeros than ones, stepping through the list and manually multiplying powers of two and adding them will be fastest.
EDIT: I re-wrote my script to use timeit, the source code is at http://pastebin.com/m6sSmmR6
My output result:
7.78366303444
2.79321694374
5.29976511002
.
5.72017598152
5.70349907875
5.66881299019
.
5.25683712959
5.17318511009
5.20052909851
.
8.23388290405
8.24193501472
8.15649604797
.
3.94102287292
3.95323395729
3.9201271534
My method of stepping through the list backwards adding powers of two is still faster if you have all zeros, but otherwise, @sxh2's method is definitely the fastest, and my implementation didn't even include his caching optimization.