25

我有这个数据:

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(第 2)个位置有“1”。

4

3 回答 3

44

itertools.groupby将具有相同键的连续项目收集在一起。如果您希望所有项目都具有相同的键,则必须先排序self.data

for mid, group in itertools.groupby(
    sorted(self.data,key=operator.itemgetter(1)), key=operator.itemgetter(1)):
于 2011-11-14T02:30:49.960 回答
30

没有排序的变体(通过字典)。在性能方面应该更好。

def full_group_by(l, key=lambda x: x):
    d = defaultdict(list)
    for item in l:
        d[key(item)].append(item)
    return d.items()
于 2013-03-06T14:37:54.933 回答
0

下面“修复”了 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)由第三个参数指定的值的干净生成器。
  4. 能够轻松应用 sum 或 avg 等聚合函数。

示例用法

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

玩这个代码

于 2019-01-10T04:46:10.720 回答