迷惑于itertools groupby总和

2024-06-02 08:07:25 发布

您现在位置:Python中文网/ 问答频道 /正文

想想这个。。。在

from itertools import groupby
from operator import itemgetter

data = [{'pid': 1, 'items': 1}, {'pid': 2, 'items': 5}, {'pid': 1, 'items': 3}]
data = sorted(data, key=itemgetter('pid'))

for pid, rows in groupby(data, lambda x: x['pid']):
    print(pid, sum(r['items'] for r in rows))
    for key in ['items']:
        print(pid, sum(r[key] for r in rows))

第一个print()调用打印右#,4表示pid1,5表示2。第二个print()调用,在通过键列表的循环中,为两个都打印0。发生什么事?在


Tags: keyinfromimportfordataitemspid
3条回答

groupby获得的rows对象是一种只能使用一次的生成器类型。当您在第一个print语句中迭代它时,您将使用这些值,因此当您下次访问并用完对其迭代功能的访问时,rows是一个空的生成器。在

如果您希望项在多个迭代过程中持久化,可以使用row_list = list(rows),然后使用row_list。在

为了更清楚地说明问题,我建议将代码放入Python REPL中,并检查该循环中的type(rows),并查看该对象提供了什么API。在

在生成器中,您遇到了一个非常常见的问题—它们只能迭代一次。itertools按规则返回生成器。在

docs for ^{}

The returned group is itself an iterator that shares the underlying iterable with groupby(). Because the source is shared, when the groupby() object is advanced, the previous group is no longer visible.

只需删除一个print()调用,并观察它的工作情况。如果需要多次访问返回的数据,则列表是一个可以保存结果的潜在结构。在

固定代码:

from itertools import groupby
from operator import itemgetter

data = [{'pid': 1, 'items': 1}, {'pid': 2, 'items': 5}, {'pid': 1, 'items': 3}]
data = sorted(data, key=itemgetter('pid'))

for pid, rows_gen in groupby(data, lambda x: x['pid']):
    rows=list(rows_gen)      # save the group to access more than once
    print(pid, sum(r['items'] for r in rows))
    for key in ['items']:
        print(pid, sum(r[key] for r in rows))

相关问题 更多 >