【问题标题】:Python itertools - Combining groupby and recipe tools' grouperPython itertools - 结合 groupby 和 recipe 工具的 grouper
【发布时间】:2015-10-22 13:10:44
【问题描述】:

假设我有以下数据:

data = [['John', 1], ['Ada', 2], ['Ada', 3], ['Paul', 4],
        ['Paul', 5], ['Paul', 6], ['Kat', 7], ['Kat', 8]]

我可以用groupby按人对条目进行分组:

In [37]:

from itertools import groupby, izip_longest
from operator import itemgetter

for name, g in groupby(data, key=itemgetter(0)):
    print name, list(g)

John [['John', 1]]
Ada [['Ada', 2], ['Ada', 3]]
Paul [['Paul', 4], ['Paul', 5], ['Paul', 6]]
Kat [['Kat', 7], ['Kat', 8]]

我还可以使用recipe tools' grouper 对每两个条目进行分组。我将复制/粘贴它以供参考:

In [38]:

def grouper(iterable, n, fillvalue=None):
    "Collect data into fixed-length chunks or blocks"
    # grouper('ABCDEFG', 3, 'x') --> ABC DEF Gxx
    args = [iter(iterable)] * n
    return izip_longest(fillvalue=fillvalue, *args)

for g in grouper(data, 2):
    print g
(['John', 1], ['Ada', 2])
(['Ada', 3], ['Paul', 4])
(['Paul', 5], ['Paul', 6])
(['Kat', 7], ['Kat', 8])

但是现在,我想遍历数据,使第一个元素包含 John 和 Ada 的数据,第二个元素包含 Paul 和 Kat 的数据。换句话说,我想像这样组合groupbygrouper

In [39]:

person_iterator = groupby(data, key=itemgetter(0))
for group_iterator in grouper(person_iterator, 2):
    print [(keyvalue[0], list(keyvalue[1])) for keyvalue in group_iterator]

但输出不是我预期的:

[('John', []), ('Ada', [['Ada', 2], ['Ada', 3]])]
[('Paul', []), ('Kat', [['Kat', 7], ['Kat', 8]])]

为什么约翰和保罗的名单是空的?如何解决?

【问题讨论】:

  • 您的期望是什么?

标签: python python-3.x itertools


【解决方案1】:

当产生下一个iterator 时,由itertools.groupby 产生的iterator (group_iterator[1]) 已用尽。

您需要先将迭代器转换为序列,然后再将其传递给grouper 以防止出现这种情况:

person_iterator = ((key, list(grp)) for key, grp in groupby(data, key=itemgetter(0)))
for group_iterator in grouper(person_iterator, 2):
    print [(key, value) for key, value in group_iterator]

输出:

[('John', [['John', 1]]), ('Ada', [['Ada', 2], ['Ada', 3]])]
[('Paul', [['Paul', 4], ['Paul', 5], ['Paul', 6]]), ('Kat', [['Kat', 7], ['Kat', 8]])]

【讨论】:

  • 谢谢!您的解决方案有效,但我仍然不明白为什么在产生下一个迭代器时迭代器会耗尽。
  • @usualme, 如果groupby 产生的迭代器在产生下一个迭代器时没有耗尽,则应该使用一些内存来保存它。
  • @usualme,我希望这 (ideone.com/I2lrWX) 能帮助你理解我的意思。
  • @usualme,或者考虑如何自己实现itertools.groupby 也会有所帮助。 (不使用不必要的内存)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多