2014-09-11 30 views
2

这是Generator to yield gap tuples from zipped iterables上的变体。生成器合并排序字典式迭代器

我希望设计发电机功能是:

  • 接受iterables
  • 每个输入迭代产生零个或多个任意数目的(K,V)中,k不一定是唯一的
  • 输入键假定按升序进行排序
  • 输出应该产生(k, (v1, v2, ...))
  • 输出键独一无二的,应用程序耳以相同的顺序与输入
  • 输出元组的数目等于唯一键的输入
  • 的输出值对应于所有输入数元组相匹配的输出密钥
  • 由于输入和输出它们可能很大,它们应该被视为可迭代的对象,并且不会作为内存中的字典或列表加载。

举个例子,

i1 = ((2, 'a'), (3, 'b'), (5, 'c')) 
i2 = ((1, 'd'), (2, 'e'), (3, 'f')) 
i3 = ((1, 'g'), (3, 'h'), (5, 'i'), (5, 'j')) 
result = sorted_merge(i1, i2, i3) 
print [result] 

这将输出:

[(1, ('d', 'g')), (2, ('a', 'e')), (3, ('b', 'f', 'h')), (5, ('c', 'i', 'j'))] 

如果我没有记错的话,没有什么内置到Python标准库做到这一点开箱。

回答

3

虽然没有一个单一的标准库函数来完成你想要什么,有enoughbuildingblocks让你最方式:

from heapq import merge 
from itertools import groupby 
from operator import itemgetter 

def sorted_merge(*iterables): 
    for key, group in groupby(merge(*iterables), itemgetter(0)): 
     yield key, [pair[1] for pair in group]  

例子:

>>> i1 = ((2, 'a'), (3, 'b'), (5, 'c')) 
>>> i2 = ((1, 'd'), (2, 'e'), (3, 'f')) 
>>> i3 = ((1, 'g'), (3, 'h'), (5, 'i'), (5, 'j')) 
>>> result = sorted_merge(i1, i2, i3) 
>>> list(result) 
[(1, ['d', 'g']), (2, ['a', 'e']), (3, ['b', 'f', 'h']), (5, ['c', 'i', 'j'])] 

注在上面的版本sorted_merge中,为了产生可读输出,我们产生intlist对。如果你想获得int<generator>双反而没有什么阻止你改变相关的行

 yield key, (pair[1] for pair in group)   

+0

我想我会做这个(除了你的建议的产生变化),唯一的修改是用一个简单的lambda来代替itemgetter。 – Reinderien 2014-09-12 17:28:59

+0

@Reinderien您的选择当然,但为什么?这正是'itemgetter'的用处......它更短,海事组织更具可读性,可能更快。 – 2014-09-12 17:33:35

+0

减少一次导入,减少一个文档必须读取的功能,另一种方法很简单。尽管如此,这只是勉强。 – Reinderien 2014-09-12 17:44:42

0

的东西有点不同:

from collections import defaultdict 

def sorted_merged(*items): 
    result = defaultdict(list) 
    for t in items: 
     for k, v in t: 
      result[k].append(v) 
    return sorted(list(result.items())) 

i1 = ((2, 'a'), (3, 'b'), (5, 'c')) 
i2 = ((1, 'd'), (2, 'e'), (3, 'f')) 
i3 = ((1, 'g'), (3, 'h'), (5, 'i'), (5, 'j')) 

result = sorted_merged(i1, i2, i3) 
+0

不幸的是默认字典会吃掉我的记忆。 – Reinderien 2014-09-11 12:55:27