[英]Fastest way to convert JavaScript object/array to Python dict/list
[英]Fastest way to convert a binary list(or array) into an integer in Python
假設有一個包含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)
還有其他更快的方法嗎?
這是我最快想到的。 您的初始解決方案略有不同:
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)]
更快。 當然,這僅在某種程度上是可行的...
編輯2:
現在,我看到您說您的列表包含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!
您可以這樣做:
sum(x << i for i, x in enumerate(reversed(gona)))
雖然不快
我決定創建一個腳本來試用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
如果全為零,我逐步遍歷列表的方法會向后加2的冪,但是,否則,@ sxh2的方法肯定是最快的,而且我的實現甚至不包括他的緩存優化。
我嘗試了這個:
int(str(gona).replace(', ','')[1:-1])
並與此相比(最快的情況是@ Sohcahtoa82):
sum(x << i for i, x in enumerate(reversed(gona)))
在我的機器上,第一個完成的時間為1000000次,傳輸時間約為5.97秒。 第二種情況需要約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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.