2016-09-25 107 views
2
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而不是自己做?


另一个海报提到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,那么key默认为一个标识函数,并且返回该元素不变。一般而言,迭代器需要在同一个按键函数上进行排序

回答

2

通常,使用迭代器的要点是避免将整个数据集保留在内存中。在你的例子中,这并不重要,因为:

  • 输入已经全部在内存中。
  • 你只是倾倒一切到dict,所以输出也都在内存中。

或者,我错过了我的用例,并且groupby应该用于其他情况?

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

假设items是一个迭代器(例如,让我们说这是从标准输入读取线)和输出比在内存中的数据结构以外的东西(如标准输出):

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

现在会少你自己做那件事很简单。