我有一个输出键和值的映射器,它被排序并通过管道输入reducer.py,
由于键已经排序,在我到达reducer之前,我想编写一个组合器,它遍历排序列表并输出将在reducer中使用的键,[v1,v2,v3]对。
cat数据| python mapper.py |排序| python reducer.py
编写reducer的最佳机制是什么,这样我就不会使用包含所有键的字典,大量的内存来保存字典中的条目。
答案 0 :(得分:4)
>>> import itertools
>>> import operator
>>> foo = [("a", 1), ("a", 2), ("b", 1), ("c", 1), ("c", 2)]
>>> for group in itertools.groupby(foo, operator.itemgetter(0)):
... print group[0], list(map(operator.itemgetter(1), group[1]))
...
a [1, 2]
b [1]
c [1, 2]
说明:
groupby
,顾名思义,基于某些关键函数将迭代的元素分组为块。也就是说,它在iterable的第一个元素上调用keyfunc
,然后从迭代中逐个拉取元素,直到keyfunc
的值发生变化,此时它会生成它已经获得的所有元素到目前为止,从新密钥开始。它也是明智的,不会消耗超过必要的内存;一旦产生价值,它们就不再由groupby
持有。
在这里,我们按operator.itemgetter(0)
对输入元素进行分组,这是一个有用的“工具箱”功能,可将x
映射到x[0]
。换句话说,我们按元组的第一个元素进行分组,这是一个键。
当然,您需要编写一个自定义生成器来处理读取输入(可能来自sys.stdin
)并逐个生成它们。幸运的是,使用yield
关键字非常简单。
另请注意,这假定键已排序。当然,如果它们没有排序,那么你无能为力:你需要查看输入的结尾,以确保你拥有给定键的所有值。