按顺序迭代多个排序列表

时间:2014-12-31 20:01:06

标签: python list iterator

假设我有许多对(int,str)列表,不一定长度相同。这里唯一的限制是列表按整数部分按升序排序:

a = [(1, 'a'), (4, 'a'), (6, 'b'), (7, 'c'), (12, 'a')]
b = [(5, 'd'), (10, 'c'), (11,'e')]
c = [(0, 'b'), (3, 'd')]

我想要做的是按照相应的整数元素出现的顺序发出字符串元素,即在这种情况下:

(0, 'b'), (1, 'a'), (3, 'd'), (4, 'a'), ... 

我想知道是否有一种明显的(漂亮的+ pythonic)方法只使用abc的迭代器?我查看了itertools,但在这种情况下无法立即查看如何使用该功能。列表abc可能非常大,所以我不想将其读入内存然后排序......

3 个答案:

答案 0 :(得分:14)

由于列表已经排序,您可以使用heapq.merge

>>> import heapq
>>> a = [(1, 'a'), (4, 'a'), (6, 'b'), (7, 'c'), (12, 'a')]
>>> b = [(5, 'd'), (10, 'c'), (11,'e')]
>>> c = [(0, 'b'), (3, 'd')]
>>> for i in heapq.merge(a, b, c):
...     i
...
(0, 'b')
(1, 'a')
(3, 'd')
(4, 'a')
(5, 'd')
(6, 'b')
(7, 'c')
(10, 'c')
(11, 'e')
(12, 'a')
>>>

这对于大型列表也非常有效,因为它在内部使用迭代器。从上面给出的文档链接:

  

sorted(itertools.chain(*iterables))类似,但返回一个   iterable,不会一次将数据拉入内存,和   假设每个输入流已经排序(最小到   最大)。

答案 1 :(得分:4)

my_iterator = iter(sorted(a+b+c))

是迄今为止最为pythonic的imho(尽管你可能只是把它作为一个列表而不是包装额外的iter

如果这是一个瓶颈(我怀疑它),你当然可以加快速度。

答案 2 :(得分:0)

heapq.merge可能是最好的选择。 FWIW more_itertools还提供了一个mergesort工具,类似于公认的接受答案:

import operator as op

import more_itertools

list(more_itertools.collate(a, b, c, key=op.itemgetter(0)))

输出

[(0, 'b'),
 (1, 'a'),
 (3, 'd'),
 (4, 'a'),
 (5, 'd'),
 (6, 'b'),
 (7, 'c'),
 (10, 'c'),
 (11, 'e'),
 (12, 'a')]

有关详细信息,请参阅more_itertools docs