2014-03-28 73 views
0

首先,我对这个问题的描述很不好。我找不到更好的。早期通过Python实现groupby的itertools.groupby的怪异

我发现将列表应用于itertools.groupby结果会破坏结果。见代码:

import itertools 
import operator 

log = '''\ 
hello world 
hello there 
hi guys 
hi girls'''.split('\n') 

data = [line.split() for line in log] 

grouped = list(itertools.groupby(data, operator.itemgetter(0))) 

for key, group in grouped: 
    print key, group, list(group) 

print '-'*80 

grouped = itertools.groupby(data, operator.itemgetter(0)) 

for key, group in grouped: 
    print key, group, list(group) 

结果是:

hello <itertools._grouper object at 0x01A86050> [] 
hi <itertools._grouper object at 0x01A86070> [['hi', 'girls']] 
-------------------------------------------------------------------------------- 
<itertools.groupby object at 0x01A824E0> 
hello <itertools._grouper object at 0x01A860B0> [['hello', 'world'], ['hello', 'there']] 
hi <itertools._grouper object at 0x01A7DFF0> [['hi', 'guys'], ['hi', 'girls']] 

也许这是关系到GROUPBY功能的内部工作。不过今天让我感到吃惊。

回答

4

这是documented

返回的基团本身是与groupby()共享迭代底层的迭代器。由于源是共享的,因此当groupby()对象进阶时,先前的组不再可见。

当你做list(groupby(...)),你一直推进groupby对象到最后,这会失去除最后一组以外的所有组。如果您需要保存组,请按照文档中的说明进行操作,并在迭代groupby对象时保存每个组。

1

文档中的例子并不像你一样:在打开迭代器组的按键的元组和列表的列表

list((key, list(group)) for key, group in itertools.groupby(...)) 

[(key,[group])]如果这就是希望。

+0

如果你想这样做,不需要使用'list',直接使用列表理解:'[(key,list(group))for key,itertools.groupby(...)]' – BrenBarn

+0

@BrenBarn在Python 2和Python 3上,Python 2和Python 2都没有相同的行为,但它泄漏了生成器表达式所没有的变量。这在Python 3中得到了修复,但是这样做会减少在list()上使用'[]'的速度。而且也不能简单地用'dict'代替'list'并取而代之'{key:[group]}'。 –