itertools.groupby()没有正确分组

时间:2011-11-14 02:29:08

标签: python itertools

我有这些数据:

self.data = [(1, 1, 5.0),
             (1, 2, 3.0),
             (1, 3, 4.0),
             (2, 1, 4.0),
             (2, 2, 2.0)]

当我运行此代码时:

for mid, group in itertools.groupby(self.data, key=operator.itemgetter(0)):

list(group)我得到了:

[(1, 1, 5.0),
 (1, 2, 3.0),
 (1, 3, 4.0)]

这就是我想要的。

但如果我使用1而不是0

for mid, group in itertools.groupby(self.data, key=operator.itemgetter(1)):

按元组中的第二个数字分组,我只得到:

[(1, 1, 5.0)]

即使其他元组在1(第二)位置有“1”,也是如此。

3 个答案:

答案 0 :(得分:21)

itertools.groupby使用相同的密钥收集连续项目。 如果您希望所有项目具有相同的密钥,则必须先对self.data进行排序。

for mid, group in itertools.groupby(
    sorted(self.data,key=operator.itemgetter(1)), key=operator.itemgetter(1)):

答案 1 :(得分:19)

没有排序的变体(通过字典)。应该是更好的表现。

def full_group_by(l, key=lambda x: x):
    d = defaultdict(list)
    for item in l:
        d[key(item)].append(item)
    return d.items()

答案 2 :(得分:2)

下面用Python的itertools.groupby“修复”了一些烦恼。

def groupby2(l, key=lambda x:x, val=lambda x:x, agg=lambda x:x, sort=True):
    if sort:
        l = sorted(l, key=key)
    return ((k, agg((val(x) for x in v))) \
        for k,v in itertools.groupby(l, key=key))

具体地说,

  1. 不需要您对数据进行排序。
  2. 不需要只将key用作命名参数。
  3. 输出是tuple(key, grouped_values)的干净生成器,其中值由第3个参数指定。
  4. 能够轻松应用求和或平均值之类的聚合函数。

用法示例

import itertools
from operator import itemgetter
from statistics import *

t = [('a',1), ('b',2), ('a',3)]
for k,v in groupby2(t, itemgetter(0), itemgetter(1), sum):
  print(k, v)

此打印,

a 4
b 2

Play with this code