【问题标题】:Iterate through multiple sorted lists in order按顺序遍历多个排序列表
【发布时间】:2014-12-31 20:01:05
【问题描述】:

假设我有许多对 (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'), ... 

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

【问题讨论】:

  • 如果不阅读它们,就没有办法做到这一点。如果你不把它们都读完,你就无法知道你没有读过的那篇是否真的应该先出来。另外,如果它们是列表,那么它们无论如何都已经在内存中了。

标签: python list iterator


【解决方案1】:

由于列表已经排序,您可以使用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)),但返回一个 可迭代,不会一次将数据全部拉入内存,并且 假设每个输入流已经排序(最小到 最大)。

【讨论】:

  • 比我的回答更高效......尤其是如果列表很大
【解决方案2】:
my_iterator = iter(sorted(a+b+c))

是迄今为止最 Pythonic 的恕我直言(尽管您可能只是将其保留为列表而不包含额外的 iter

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

【讨论】:

  • 列表已经排序。无需再次对它们进行排序。在这种情况下 heapq.merge() 是一个更好的选择。
【解决方案3】:

heapq.merge 可能是最佳选择。 FWIW more_itertools 还提供了一个合并排序工具,类似于公认的答案:

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

【讨论】:

    猜你喜欢
    • 2017-07-29
    • 1970-01-01
    • 2013-07-01
    • 1970-01-01
    • 2013-07-13
    • 1970-01-01
    • 1970-01-01
    • 2013-05-29
    • 2013-08-29
    相关资源
    最近更新 更多