itertools.groupby()没有正确分组

use*_*165 11 python python-itertools

我有这些数据:

self.data = [(1, 1, 5.0),
             (1, 2, 3.0),
             (1, 3, 4.0),
             (2, 1, 4.0),
             (2, 2, 2.0)]
Run Code Online (Sandbox Code Playgroud)

当我运行此代码时:

for mid, group in itertools.groupby(self.data, key=operator.itemgetter(0)):
Run Code Online (Sandbox Code Playgroud)

因为list(group)我得到:

[(1, 1, 5.0),
 (1, 2, 3.0),
 (1, 3, 4.0)]
Run Code Online (Sandbox Code Playgroud)

这就是我想要的.

但是,如果我使用1而不是0

for mid, group in itertools.groupby(self.data, key=operator.itemgetter(1)):
Run Code Online (Sandbox Code Playgroud)

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

[(1, 1, 5.0)]
Run Code Online (Sandbox Code Playgroud)

即使有其他元组在1(第二)位置有"1".

unu*_*tbu 23

itertools.groupby使用相同的密钥收集连续的项目.如果您想要所有具有相同键的项目,则必须先排序self.data.

for mid, group in itertools.groupby(
    sorted(self.data,key=operator.itemgetter(1)), key=operator.itemgetter(1)):
Run Code Online (Sandbox Code Playgroud)

  • 无需排序;你想使用 *dictionary* 代替: `grouped = {}` 然后 `for v in self.data: grouped.setdefault(v[1], []).append(v)`。排序是一个 O(NlogN) 操作,使用字典对值进行分组可以让您在 O(N) 时间内完成任务。 (5认同)

Kos*_*kov 20

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

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

  • 不幸的是,所有的键都必须是可散列的,因此如果这些键用于示例列表,则它不起作用,与 `itertools.groupby` 不同...... (2认同)
  • @Jeronimo:你会尝试找到密钥的可哈希反射;例如,对于列表键,可以使用“tuple()”;对于字典,可以使用“frozenset(d.items())”。如果这确实不可能,那么您就必须回退到 O(NlogN) 的排序成本。使用字典进行分组可以让您在线性 (O(N)) 时间内完成任务。 (2认同)