假设有一个包含1和0的列表(或数组)。
gona = [1, 0, 0, 0, 1, 1]
我想将其转换为二进制值100011
表示的整数(由列表中的元素组成的数字)。
我知道这可以按照以下方式完成。
int("".join(map(str, gona)),2)
或
编辑:int("".join([str(i) for i in gona]),2)
还有其他更快捷的方法吗?
答案 0 :(得分:4)
这是我想出的最快的。您的初始解决方案略有不同:
digits = ['0', '1']
int("".join([ digits[y] for y in x ]), 2)
%timeit int("".join([digits[y] for y in x]),2)
100000 loops, best of 3: 6.15 us per loop
%timeit int("".join(map(str, x)),2)
100000 loops, best of 3: 7.49 us per loop
(顺便说一句,在这种情况下,使用列表推导似乎比使用生成器表达式更快。)
编辑:
另外,我讨厌成为智能手机,但你总是可以换取记忆速度:
# one time precalculation
cache_N = 16 # or much bigger?!
cache = {
tuple(x): int("".join([digits[y] for y in x]),2)
for x in itertools.product((0,1), repeat=cache_N)
}
然后:
res = cache[tuple(x)]
方式更快。当然,这只是一点点可行......
EDIT2:
我现在看到你说你的名单有32个元素。在这种情况下,缓存解决方案可能是不可行的,但我们有更多的方式来换取内存的速度。例如,cache_N=16
,这肯定是可行的,你可以访问它两次:
c = 2 ** cache_N # compute once
xx = tuple(x)
cache[xx[:16]] * c + cache[xx[16:]]
%timeit cache[xx[:16]] * c + cache[xx[16:]]
1000000 loops, best of 3: 1.23 us per loop # YES!
答案 1 :(得分:2)
你可以这样做:
sum(x << i for i, x in enumerate(reversed(gona)))
虽然速度不是很快
答案 2 :(得分:2)
我决定创建一个脚本来试用4种不同的方法来完成这项任务。
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)
我的结果:
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
结论:@ goncalopp的解决方案可能是最好的解决方案。它一直很快。另一方面,如果您可能有更多的零,那么单步执行列表并手动乘以2的幂并添加它们将是最快的。
编辑:我重新编写了我的脚本以使用timeit,源代码位于http://pastebin.com/m6sSmmR6
我的输出结果:
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
如果你有全零的话,我向后逐步加入列表的方法仍然会更快,但是否则,@ sxh2的方法肯定是最快的,我的实现甚至不包括他的缓存优化。
答案 3 :(得分:1)
我试过了:
int(str(gona).replace(', ','')[1:-1])
与此相比(这是@ Sohcahtoa82最快的情况):
sum(x << i for i, x in enumerate(reversed(gona)))
在我的机器上,第一个在~5.97秒内完成1000000次传球。第二种情况需要~8.03s。
我尝试了另一种方法,并插入@ Sohcahtoa82的代码:
T61 = """
l = [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,1,1]
digits = ['0', '1']
s = ''
for y in l:
s += digits[y]
int(s, 2)
"""
T60 = """
l = [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]
digits = ['0', '1']
s = ''
for y in l:
s += digits[y]
int(s, 2)
"""
T6mix = """
l = [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]
digits = ['0', '1']
s = ''
for y in l:
s += digits[y]
int(s, 2)
"""
得到了这些结果。我是最后一次。
5.45334255339
1.89000112578
4.14859673729
.
4.39018410496
4.21122597336
4.57919181895
.
3.59095765307
3.25353409619
3.78588067833
.
6.53343932548
6.33234985363
6.65685678006
.
2.74509861151
2.6111819044
2.83928911064
.
2.79519545737
2.66091503704
2.9183024407