我怎样才能在python中使用排序输出进行izip?

时间:2012-05-19 15:05:36

标签: sorting iterator python yield

由于缺少一个更好的名字,我想在Python中做一个“izip_sorted”。函数的输入是许多可迭代的,每个都是有序的。输出是具有有序输出的单个可迭代。

print([x for x in izip_sorted([0,4,8], [1,3,5], [12,12,42],[])])

编辑:这是一个简单的例子。实际使用将是大约40个输入迭代,每个迭代有大约100000个元素。每个元素都是一个存储dict的类,并实现__cmp__,以便对元素进行排序。数据太大,无法一次性读取。

应该打印

[0, 1, 3, 4, 5, 8, 12, 12, 42]

我有一个解决方案,但我是python的新手,我不知道它是非常 Pythonic 。这可以改进吗?只有1个元素发生变化的排序似乎很浪费......

def izip_sorted(*iterables):
    """
    Return an iterator that outputs the values from the iterables, in sort order
    izip_sort('ABF', 'D', 'CE') --> A B C D E F
    """
    iterators = [iter(it) for it in iterables]
    current_iterators = []
    for it in iterators:
        try:
            current_iterators.append((next(it), it))
        except StopIteration:
            pass
    current_iterators.sort(key=lambda x: x[0])
    while(current_iterators):
        yield current_iterators[0][0]
        try:
            current_iterators[0] = (next(current_iterators[0][1]), current_iterators[0][1])
            current_iterators.sort(key=lambda x: x[0])
        except StopIteration:
            current_iterators = current_iterators[1:]

4 个答案:

答案 0 :(得分:4)

我认为你要找的是链接迭代的所有值,然后对它们进行排序。为此,我们可以简单地合并itertools.chain()the sorted() builtin

>>> from itertools import chain
>>> sorted(chain([0,4,8], [1,3,5], [12,12,42],[]))
[0, 1, 3, 4, 5, 8, 12, 12, 42]

如果你有一个可迭代的列表,你可能想要使用itertools.chain.from_iterable()

>>> iterables = [[0,4,8], [1,3,5], [12,12,42],[]]
>>> sorted(chain.from_iterable(iterables))
[0, 1, 3, 4, 5, 8, 12, 12, 42]

编辑:对于您确切的问题,如果您知道输入列表已排序,并且每个输入列表的最后一项不会大于下一个列表的第一项,我们只需根据第一个值进行排序(使用sorted()的关键功能)然后链接它们。

>>> from operator import itemgetter
>>> iterables = [[0,4,8], [1,3,5], [12,12,42]]
>>> sorted(iterables, key=itemgetter(0))
[[0, 4, 8], [1, 3, 5], [12, 12, 42]]
>>> list(chain.from_iterable(sorted(iterables, key=itemgetter(0))))
[0, 4, 8, 1, 3, 5, 12, 12, 42]

问题是,您提供给我们的数据不符合这些规则,因此答案不正确。

答案 1 :(得分:3)

如果输入没有排序,则必须全部实现(实际上,从可迭代变为列表)。如果不查看数据,就无法排序。 LattyWare's solution是最蟒蛇的。

另一方面,如果已知输入的可迭代内容已排序,则可以使用heapq.merge

>>> from heapq import merge
>>> merge(*iterables)

答案 2 :(得分:2)

这不是zipzip将几个iterables拉成可迭代的元组。你的功能很简单:

sorted(itertools.chain(*iterables))

答案 3 :(得分:0)

您也可以这样做:

sorted([item for iterable in iterables for item in iterable])