2016-06-12 84 views
4

我有一個字典dct爲此,我想它的每個值要進行求和提供了一種在指定列表存在lst它們相應的密鑰。過濾器值的表達式

我使用至今的代碼是:

sum(dct[k] for k in lst) 

在上述發電機表達我想處理KeyError的情況下,從列表中的一個關鍵的字典裏是找不到的。我似乎無法找到如何在此生成器表達式中實現(按語法)try - except方法或者if - else方法。

如果字典中沒有找到列表中的鍵,則應該繼續獲取其他值總和的最終結果不應受任何丟失的鍵影響。如果沒有任何鍵存在,那麼零應該是總和的結果。

+1

您不能在生成器表達式中使用'try'。爲什麼不使用'dct.get(k)',如果找不到密鑰,會給你'None'而不是錯誤?在沒有找到密鑰的情況下(例如,它應該計爲「0」),代碼的正確行爲是什麼? – jonrsharpe

+0

如果找不到密鑰,則應繼續使用其餘密鑰。 (我會更新我的描述來解釋這種情況 - 感謝您注意到這一點) – Yannis

回答

1

嗯,有幾個選項,首選1是使用dict.get()

# 1 
sum(dct.get(k, 0) for k in lst) 
# 2 
sum(dct[k] for k in lst if k in dct) 

另一個選項是在迭代之前過濾lst

sum(dct[k] for k in filter(lambda i: i in dct, lst)) 

你可以過濾列表上使用reduce function作爲替代sum

reduce(lambda a, k: a + dct[k], filter(lambda i: i in dct, lst)) 

現在,讓我們找到最快的方式與timeit

from timeit import timeit 
import random 

lst = range(0, 10000) 
dct = {x:x for x in lst if random.choice([True, False])} 

via_sum = lambda:(sum(dct.get(k, 0) for k in lst)) 
print("Via sum and get: %s" % timeit(via_sum, number=10000)) 
# Via sum and get: 16.725695848464966 

via_sum_and_cond = lambda:(sum(dct[k] for k in lst if k in dct)) 
print("Via sum and condition: %s" % timeit(via_sum_and_cond, number=10000)) 
# Via sum and condition: 9.4715681076 

via_reduce = lambda:(reduce(lambda a, k: a + dct[k], filter(lambda i: i in dct, lst))) 
print("Via reduce: %s" % timeit(via_reduce, number=10000)) 
# Via reduce: 19.9522120953 

所以最快的選項是通過如內聲明,總結項目發生器表達

sum(dct[k] for k in lst if k in dct) # Via sum and condition: 9.4715681076 

好Luc k!

+0

偉大而完整的答案。好奇的是,如果你能夠提供一些洞察力來比較這4個選項;具體來說,第三個選項與前兩個選項相比如何。他們之間是否有任何提高效率的方法或更多的「Pythonic」方法? – Yannis

+0

@Yannis謝謝,當然)看到更新的答案與時間指標:)我的猜測贏家方法是最'Pythonic')) –

1
sum(dct[k] for k in lst if k in dct) 
+0

確實有用的答案;其他人也提到了這種方法,並且從我所看到的情況來看,你的並不是最快的。對不起 – Yannis

2

您可以簡單地使用.get()試圖獲取從字典中鍵的值,它應該不會被發現會返回None,或者您提供的默認參數,它會在這種情況下是0。

>>> dct = {1:2, 3:4, 5:6} 
>>> lst = [1,5] 
>>> sum(dct.get(k, 0) for k in lst) 
8  

如果該鍵的一些(或全部)不存在,總和仍可正常工作。

>>> lst = [10, 11] 
>>> sum(dct.get(k, 0) for k in lst) 
0 
5

你有兩個選擇:

檢查如果該鍵存在

sum(dct[k] for k in lst if k in dct) 

或使用get

sum(dct.get(k, 0) for k in lst) 

其中dct.get(k, 0)回報dct[k]如果k是一個關鍵的dct或如果不是,則爲0

1

您可以使用字典的get - 方法,提供一個默認值,如果沒有找到:

sum(dct.get(k, 0) for k in lst)