试着想出一个单行程来实现以下功能(总结一个键的所有值):
>>> data = [('a',1),('b',3),('a',4),('c',9),('b',1),('d',3)]
>>> res = {}
>>> for tup in data:
... res[tup[0]] = res.setdefault(tup[0],0) + tup[1]
...
>>> res
{'a': 5, 'c': 9, 'b': 4, 'd': 3}
单行版本,不使用任何导入,如itertools,集合等。
{ tup[0] : SELF_REFERENCE.setdefault(tup[0],0) + tup[1] for tup in data }
在Python中是否可以使用对当前正在理解的对象的引用? 如果没有,有没有办法在单线程中实现这一点而不使用任何进口,即使用 基本列表/词典理解和内置函数。
答案 0 :(得分:6)
不,没有。 dict理解为每次迭代生成 new 项,并且您的代码需要生成更少的项(合并值)。
无法使用(丑陋的,unpythonic)副作用技巧,无法访问先前迭代中生成的键。由理解产生的dict
对象尚不存在,因此也无法产生自引用。
坚持你的for
循环,它更具可读性。
另一种方法是使用排序和分组,O(NlogN)算法与直接循环的简单O(N):
from itertools import groupby
from operator import itemgetter
res = {key: sum(t[1] for t in group)
for key, group in groupby(sorted(data, key=itemgetter(0)), key=itemgetter(0))}
答案 1 :(得分:2)
不要使用oneliner。而是使用collections.defaultdict
和一个简单的for循环:
>>> pairs = [('a', 1), ('b', 3), ('a', 4), ('c', 9), ('b', 1), ('d', 3)]
>>> result = defaultdict(int)
>>> for key, value in pairs:
... result[key] += value
...
>>> result
defaultdict(<class 'int'>, {'a': 5, 'c': 9, 'b': 4, 'd': 3})
易于理解,pythonic和快速。
答案 2 :(得分:1)
>>> from operator import add
>>> from collections import Counter
>>> reduce(add, (Counter(dict([x])) for x in data))
Counter({'c': 9, 'a': 5, 'b': 4, 'd': 3})
答案 3 :(得分:1)
这几乎就像你想要做的那样。但我不建议这样做,因为可读性会受到影响。
data = [('a',1),('b',3),('a',4),('c',9),('b',1),('d',3)]
print reduce(lambda d,i: [d.__setitem__(i[0],d.get(i[0],0)+i[1]),d][1], data, {})
<强>输出强>
{'a': 5, 'c': 9, 'b': 4, 'd': 3}