Filter values inside Python generator expressions

血红的双手。 提交于 2019-12-10 15:53:50

问题


I have a dictionary dct for which I want each of its values to be summed provided their corresponding keys exist in a specified list lst.

The code I am using so far is:

sum(dct[k] for k in lst)

In the above generator expression I would like to handle the KeyError in case a key from the list is not found inside the dictionary. I cannot seem to find how to implement (syntax-wise) either a try-except approach, nor an if-else approach inside this generator expression.

In case a key from the list is not found inside the dictionary, then it should carry on getting the other values. The end result of the sums should not be affected by any missing keys. In case none of the keys exist, then zero should be the sum's result.


回答1:


Well, there are few options, preferred one is to use dict.get():

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

Also one of the option is to filter lst before iteraring over it:

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

And you can use reduce function on filtered list as an alternative to sum:

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

Now let's find fastest approach with 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

So the fastest option is to sum items via if statement within generator expression

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

Good Luck !




回答2:


You have two options:

Checking if the key exists

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

or using get

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

where dct.get(k, 0) returns dct[k] if k is a key in dct or 0 if not.




回答3:


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



回答4:


You can use the get-method of dictionaries, to provide a default value if not found:

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



回答5:


You can simply use .get() to attempt to get the value for the key from the dictionary, and should it not be found will return None, or your provided default parameter which would be 0 in this case.

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

Should some (or all) of the keys not exist, the sum will still function properly.

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


来源:https://stackoverflow.com/questions/37772551/filter-values-inside-python-generator-expressions

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!