【问题标题】:Python list group by keyPython列表分组键
【发布时间】:2021-07-05 14:33:49
【问题描述】:

我有一个清单:

x = [[17, 2], [18, 4], [17, 2], [18, 0], [19, 4],
     [17, 4], [19, 4], [17, 4], [20, 4], [17, 4],
     [20, 4], [17, 4], [17, 4], [18, 4], [17, 4]]

当第一个值相同时,我想对所有第二个值求和。

例如:17 = 28...

我尝试用 :

d = {}
for row in x:
    if row[0] not in d:
        d[row[0]] = []
    d[row[0]].append(row[1])

结果是

{17: [2, 2, 4, 4, 4, 4, 4, 4],
 18: [4, 0, 4], 19: [4, 4],
 20: [4, 4]}

我没有找到对这些值求和的方法。

【问题讨论】:

  • 你正在取所有数字的总和
  • 由于您对总和而不是列表感兴趣,请将 d[row[0]] = [] 替换为 d[row[0]] = 0 并将 d[row[0]].append(row[1]) 替换为 d[row[0]] += row[1] 以实际求和而不是列出它们。
  • 相关问题:Reduce by key in python

标签: python dictionary math


【解决方案1】:

如果列表已排序,您可以使用itertools.groupby(并且您可以使用sorted 来确保):

from itertools import groupby
from operator import itemgetter

d = {key: sum(grp) for key, grp in groupby(sorted(x, key=itemgetter(0)))}

在这种情况下,itemgetter(0) 是lambda x: x[0] 的更有效的快捷方式。

在您原来的情况下,您可以保持一个运行总和或之后的总和。总结你已经拥有的字典:

d = {k: sum(v) for k, v in d.items()}

要保持流动总和:

d = {}
for k, v in x:
    if k in d:
        d[k] += v
    else:
        d[k] = v

做同样事情的更短的方法是使用dict.setdefault:

d = {}
for k, v in x:
    d[k] = d.setdefault(k, 0) + v

【讨论】:

  • 您能否分享您的想法,为什么 itemgetter(0) 比 lambda 更有效?我不是质疑它,只是试图理解。我会用 lambda 写,因为对我来说,对于每个内部列表,我想按第一个/第二个元素进行排序/分组/过滤。
  • @AhsanulHaque。当然。 itemgetter(0) 专门用 C(在 CPython 中)编写,以使其成为提供排序键的更有效方式。我已经为我推荐的所有功能添加了文档链接。
【解决方案2】:

使用默认字典:

>>> from collections import defaultdict
>>> d = defaultdict(int)
>>> for lst in x:
...   a, b = lst
...   d[a] +=  b
>>> d
defaultdict(int, {17: 28, 18: 8, 19: 8, 20: 8})

【讨论】:

  • 你可以做for a, b in x:
【解决方案3】:

我们在这里:

x=[[17, 2], [18, 4], [17, 2], [18, 0], [19, 4], [17, 4], [19, 4], [17, 4], [20, 4], [17, 4], [20, 4], [17, 4], [17, 4], [18, 4], [17, 4]]
d = {}
for row in x:
    if row[0] not in d:
        d[row[0]] = 0
    d[row[0]] += row[1]

print(d)

输出是

{17: 28, 18: 8, 19: 8, 20: 8}

【讨论】:

  • d[row[0]] = row[1] 应该是d[row[0]] = 0
  • 否则,您将添加每个组中的第一个元素两次。 20: 4 + 4 = 8 你可以轻易看到这个,但你报告的是4 + 4 + 4 = 12
猜你喜欢
  • 1970-01-01
  • 2011-01-15
  • 2019-06-29
  • 1970-01-01
  • 1970-01-01
  • 2017-04-11
  • 2016-08-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多