[英]Fastest way to increment counters in dictionary
增加存儲在字典中的計數器的最快方法是什么?
因為我必須完成相同的操作數十萬次,所以我正在尋找比我下面更有效的東西:
def funcA(a):
keys = [x for x in range(1, 51)]
adict = {key: 0 for key in keys}
for k in adict.keys(): # this is the code I would like to improve
if k <= a:
adict[k] += 1
else:
break
import timeit
number = 100000
t1 = timeit.timeit(
'funcA(5)',
setup="from __main__ import funcA", number=number)
print(t1)
>>> 0.42629639082588255
試圖使用列表理解而不是似乎減慢了一切,可能是因為它缺少break
語句?
def funcB(a):
# not working, invalid syntax
keys = [x for x in range(1, 51)]
adict = {key: 0 for key in keys}
def _inc(x):
x += 1
return x
[_inc(adict[k]) for k in adict.keys() if k <= a]
# Timing: 0.5831785711925477
注意:最初我有if float(k) <= float(a):
但由於我只期望數字(整數或浮點數),刪除float()
轉換改進了代碼。 這個假設合理嗎?
注意2:如幾條評論中所述, break
語句可以在結果字典中產生意外結果,因此最好只做:
def funcA(a):
keys = [x for x in range(1, 51)]
adict = {key: 0 for key in keys}
for k in adict:
if k <= a:
adict[k] += 1
# Timing: 0.5132114209700376
在你的情況下,你可以使用布爾(比較的結果)可以簡單地轉換為整數的事實。 它可能不是最快但它肯定是短的並且“相對”快:
def funcA(a):
adict = {key: int(key <= a) for key in range(1, 51)}
這假設第二個函數實際上是你想要的,因為第一個函數可以因為break
而給出不同的結果。 字典是無序的,因此無法為小於或等於a
鍵增加某些值。 此外,它不會增加值,它只是將它們設置為1
或0
因為在這種情況下您實際上不需要添加。
但是,這不一定是最快的方式,因為它必須執行大量的函數調用和int
查找。 因此,我將按性能順序(最快到最慢)呈現一些更等效的操作:
def cached_version():
range_cache = range(1, 51)
cache = dict.fromkeys(range_cache, 0)
def inner(a):
adict = cache.copy()
for key in range_cache[:a]: # requires a to be an integer!
adict[key] = 1
return adict
return inner
func1 = cached_version() # initialize cache
def func2(a):
keys = range(1, 51)
adict = dict.fromkeys(keys[:a], 1) # requires a to be an integer!
for key in keys[a:]:
adict[key] = 0
return adict
def func3(a):
adict = {}
for key in range(1, 51):
if key <= a:
adict[key] = 1
else:
adict[key] = 0
return adict
def func4(a):
return {key: 1 if key <= a else 0 for key in range(1, 51)}
def func5(a):
keys = range(1, 51)
adict = dict.fromkeys(keys[:a], 1) # requires a to be an integer!
adict.update(dict.fromkeys(keys[a:], 0))
return adict
def func6(a):
return dict(zip(range(1, 51), [1]*a + [0]*(49-a))) # requires a to be an integer!
from itertools import chain
def func7(a):
return dict(zip(range(1, 51), chain([1]*a, [0]*(49-a)))) # requires a to be an integer!
def func8(a): # the one I originally mentioned
adict = {key: int(key <= a) for key in range(1, 51)}
時間安排在Python 3.5,Windows 10上完成,其他機器和其他Python版本可能存在差異。 另請注意,如果您有更多的鍵而不僅僅是range(1, 51)
,性能可能會完全不同。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.