假设我有许多对(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)方法只使用a
,b
和c
的迭代器?我查看了itertools
,但在这种情况下无法立即查看如何使用该功能。列表a
,b
,c
可能非常大,所以我不想将其读入内存然后排序......
答案 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。