簡體   English   中英

在字典中增加計數器的最快方法

[英]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鍵增加某些值。 此外,它不會增加值,它只是將它們設置為10因為在這種情況下您實際上不需要添加。

但是,這不一定是最快的方式,因為它必須執行大量的函數調用和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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM