为什么要使用itertools.groupby而不是自己实现?

4
from collections import defaultdict
import itertools

items = [(0, 0), (0, 1), (1, 0), (1, 1)]

keyfunc = lambda x: x[0]

# Grouping yourself
item_map = defaultdict(list)
for item in items:
    item_map[keyfunc(item)].append(item)

# Using itertools.groupby
item_map = {}
for key, group in itertools.groupby(items, keyfunc):
    item_map[key] = [i for i in group]

为什么我应该使用 itertools.groupby 而不是自己编写代码?它是否可以在更少的时间复杂度下执行分组操作?或者,我的用例有什么遗漏,需要使用 groupby 处理其他情况?


另一个帖子提到,如果要分组的项没有按键排序(或者只是键连续),itertools.groupby将返回不同的结果。

例如,对于items = [(0, 0), (1, 1), (0, 2)],如果我们不按键排序,itertools.groupby将返回

{0: [(0, 2)], 1: [(1, 1)]}

而我的实现返回

{0: [(0, 0), (0, 2)], 1: [(1, 1)]}

除非我误解了重点,否则DIY方法似乎更好,因为它不需要对数据进行排序。
这是文档
创建一个迭代器,从可迭代对象中返回连续的键和组。键是计算每个元素的键值的函数。如果未指定或为None,则键默认为身份函数,并返回未更改的元素。通常,可迭代对象需要在相同的键函数上已经排序。
1个回答

3
通常使用迭代器的目的是避免将整个数据集保存在内存中。在您的示例中,这并不重要,因为:
  • 输入已经全部在内存中。
  • 您只是将所有内容转储到一个 dict 中,因此输出也全部在内存中。

或者,我在我的用例中错过了什么,groupby 应该用于其他情况吗?

我认为这是一个准确的评估。

假设 items 是一个迭代器(例如,它是从 stdin 读取的行),并且输出是一些不同于内存数据结构的东西(例如 stdout):

for key, group in itertools.groupby(items, keyfunc):
    print("{}: {}".format(key, str([i for i in group])))

现在如果你自己去做这件事就不那么琐碎了。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接