2

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)]
4

2 に答える 2

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 反復子が基になるデータ反復子をラップすることは、 acsv.readerが基になるファイル オブジェクト反復子をラップする方法に似ています。この反復子を介して 1 つのパスを取得し、1 つのパスのみを取得します。itertools.izip 関数は、 の項目をペアにするプロセスでgroupsgroups反復子を最初の項目から 2 番目の項目に進めます。イテレータを通過するのは 1 回だけなので、最初の項目は消費されているので、呼び出しlist(g[1])たときは空です。

この問題のあまり満足のいく修正は、イテレータgroupsをリストに変換することです:

groups = (list(group) for key, group in groups)

したがって、itertools.izipそれらを時期尚早に消費することはありません。編集: よく考えてみると、この修正はそれほど悪くはありません。はイテレータのままで、消費されるとリストにgroups変わるだけです。group

于 2013-02-14T13:35:06.317 に答える
2

から 2 番目のキーを見ようとするとgroupby、ソース イテレータまで反復するよう強制されます。通常、最初のグループのアイテムを格納する場所がないため、単純に破棄されます。

これで、2 番目のグループのキー (または項目) を調べる前に、最初のグループの項目を保存したことを確認する必要がある理由がわかりました。

これを嫌う人もいるでしょうが、

>>> 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)]
于 2013-02-14T13:44:11.700 に答える