如何成对迭代groupby
个结果?我尝试的不太合适:
from itertools import groupby,izip
groups = groupby([(1,2,3),(1,2),(1,2),(3,4,5),(3,4)],key=len)
def grouped(iterable, n):
return izip(*[iterable]*n)
for g, gg in grouped(groups,2):
print list(g[1]), list(gg[1])
输出我得到:
[] [(1, 2), (1, 2)]
[] [(3, 4)]
输出我想:
[(1, 2, 3)] [(1, 2), (1, 2)]
[(3, 4, 5)] [(3, 4)]
答案 0 :(得分:2)
import itertools as IT
groups = IT.groupby([(1,2,3),(1,2),(1,2),(3,4,5),(3,4)], key=len)
groups = (list(group) for key, group in groups)
def grouped(iterable, n):
return IT.izip(*[iterable]*n)
for p1, p2 in grouped(groups, 2):
print p1, p2
产量
[(1, 2, 3)] [(1, 2), (1, 2)]
[(3, 4, 5)] [(3, 4)]
您发布的代码非常有趣。它有一个平凡的问题,一个微妙的问题。
世俗的问题是itertools.groupby返回一个迭代器,它在每次迭代时都输出一个键和一个组。 由于您只对组感兴趣,而不是键,所以需要像
这样的东西groups = (group for key, group in groups)
微妙的问题更难以解释 - 我不确定我是否完全理解它。我的猜测是:groupby
返回的迭代器已经改变了输入,
[(1,2,3),(1,2),(1,2),(3,4,5),(3,4)]
进入迭代器。 groupby迭代器包含在底层数据迭代器中,类似于csv.reader
围绕底层文件对象迭代器的方式。你通过这个迭代器得到一次通过,只有一次通过。在groups
中配对项目的过程中,itertools.izip函数会导致groups
迭代器从第一个项目前进到第二个项目。由于您只通过迭代器一次,所以第一项已被消耗,因此当您调用list(g[1])
时它是空的。
不那么令人满意修复此问题的方法是将groups
中的迭代器转换为列表:
groups = (list(group) for key, group in groups)
所以itertools.izip
不会过早消耗它们。编辑:第二个想法,这个修复并不是那么糟糕。 groups
仍然是一个迭代器,只有在group
消耗时才将{{1}}转换为列表。
答案 1 :(得分:2)
当您尝试查看groupby
中的第二个键时,您将强制它迭代到源迭代器中。由于通常无处存储来自第一组的物品,因此它们被丢弃。
现在我们理解为什么在尝试查看第二组的键(或项目)之前,我们需要确保已存储第一组中的项目。
有些人肯定讨厌这个,但
>>> groups = groupby([(1, 2, 3), (1, 2), (1, 2), (3, 4, 5), (3, 4)], key=len)
>>> for i, j in ((list(i[1]), list(next(groups)[1])) for i in groups):
... print i, j
...
[(1, 2, 3)] [(1, 2), (1, 2)]
[(3, 4, 5)] [(3, 4)]