为什么要使用itertools.groupby而不是自己动手?

时间:2016-09-25 03:18:34

标签: python

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方法更好,因为它不需要对数据进行排序。

以下是documentation

  

创建一个迭代器,从迭代中返回连续的键和组。关键是计算每个元素的键值的函数。如果未指定或为None,则键默认为标识函数并返回元素不变。通常,迭代需要已经在相同的键函数

上排序

1 个答案:

答案 0 :(得分:3)

通常,使用迭代器的目的是避免将整个数据集保存在内存中。在您的示例中,它无关紧要,因为:

  • 输入已全部在内存中。
  • 您只是将所有内容转储到dict,因此输出也全部都在内存中。
  

或者,我是否错过了我的用例,而groupby应该用于其他情况?

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

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

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

现在自己做这件事并不是那么简单。