在Python中进行list / dict理解时是否可以访问当前对象?

时间:2014-01-14 11:48:07

标签: python list-comprehension dictionary-comprehension

试着想出一个单行程来实现以下功能(总结一个键的所有值):

>>> 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中是否可以使用对当前正在理解的对象的引用? 如果没有,有没有办法在单线程中实现这一点而不使用任何进口,即使用 基本列表/词典理解和内置函数。

4 个答案:

答案 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)

使用reducecollections.Counter

>>> 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}