【问题标题】:Is it possible to access current object while doing list/dict comprehension in Python?在 Python 中进行列表/字典理解时是否可以访问当前对象?
【发布时间】:2014-02-02 11:15:59
【问题描述】:

试图想出一个单线来实现以下目标(对一个键的所有值求和):

>>> 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、collections 等。

 { tup[0] : SELF_REFERENCE.setdefault(tup[0],0) + tup[1]  for tup in data }

是否可以在 Python 中使用对当前正在理解的对象的引用? 如果没有,是否有任何方法可以在不使用任何导入的情况下在单行中实现这一点,即使用 基本的列表/字典理解和内置函数。

【问题讨论】:

  • SELF_REFERENCE 正在建设中,在理解中:)
  • 你可以改为sum((Counter(dict([x])) for x in data), Counter())...

标签: python list-comprehension dictionary-comprehension


【解决方案1】:

不,没有。 dict 理解为每次迭代生成一个 项,您的代码需要生成 更少 项(合并值)。

没有办法访问在早期迭代中生成的密钥,而不是使用(丑陋的,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))}

【讨论】:

    【解决方案2】:

    使用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})
    

    【讨论】:

    • 注意:在 Python 3 中,reduce 方法已移至 functools 包中。
    【解决方案3】:

    不要使用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 和快速。

    【讨论】:

      【解决方案4】:

      这几乎就像你正在尝试做的事情。但我不会推荐这个,因为可读性会受到影响。

      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}
      

      【讨论】:

      • 这个解决方案伤害了我的眼睛 :-)
      • @Abhijit 我说对不起:(
      猜你喜欢
      • 2021-06-08
      • 2013-01-29
      • 2023-04-06
      • 1970-01-01
      • 2021-08-04
      • 1970-01-01
      • 2015-07-03
      相关资源
      最近更新 更多