9

为了说明,我从一个 2 元组列表开始:

import itertools
import operator

raw = [(1, "one"),
       (2, "two"),
       (1, "one"),
       (3, "three"),
       (2, "two")]

for key, grp in itertools.groupby(raw, key=lambda item: item[0]):
    print key, list(grp).pop()[1]

产量:

1 one
2 two
1 one
3 three
2 two

试图调查原因:

for key, grp in itertools.groupby(raw, key=lambda item: item[0]):
    print key, list(grp)

# ---- OUTPUT ----
1 [(1, 'one')]
2 [(2, 'two')]
1 [(1, 'one')]
3 [(3, 'three')]
2 [(2, 'two')]

即使这会给我相同的输出:

for key, grp in itertools.groupby(raw, key=operator.itemgetter(0)):
    print key, list(grp)

我想得到类似的东西:

1 one, one
2 two, two
3 three

我认为这是因为键在列表内的元组内,而实际上元组作为一个移动。有没有办法达到我想要的输出?也许groupby()不适合这个任务?

4

3 回答 3

13

groupby将具有相同键的可迭代的连续元素聚集在一起。要产生您想要的输出,您必须首先对raw.

for key, grp in itertools.groupby(sorted(raw), key=operator.itemgetter(0)):
    print key, map(operator.itemgetter(1), grp)

# 1 ['one', 'one']
# 2 ['two', 'two']
# 3 ['three']
于 2010-08-09T13:42:26.830 回答
7

我认为获得所需结果的更清洁方法是这样。

>>> from collections import defaultdict
>>> d=defaultdict(list)
>>> for k,v in raw:
...  d[k].append(v)
... 
>>> for k,v in sorted(d.items()):
...  print k, v
... 
1 ['one', 'one']
2 ['two', 'two']
3 ['three']

构建d是 O(n),现在sorted()只是在唯一键上而不是整个数据集上

于 2010-08-09T22:30:28.933 回答
3

文档

groupby() 的操作类似于 Unix 中的 uniq 过滤器。每次键函数的值发生变化时,它都会生成一个中断或新组(这就是为什么通常需要使用相同的键函数对数据进行排序的原因)。这种行为与 SQL 的 GROUP BY 不同,后者聚合公共元素,而不管它们的输入顺序如何。

由于您无论如何都按字典顺序对元组进行排序,因此您可以调用sorted

for key, grp in itertools.groupby( sorted( raw ), key = operator.itemgetter( 0 ) ):
    print( key, list( map( operator.itemgetter( 1 ), list( grp ) ) ) )
于 2010-08-09T13:45:47.870 回答