1

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

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

编辑:这是一个简单的例子。真正的用途将是大约 40 个输入迭代,每个迭代大约有 100000 个元素。每个元素都是一个类,存储一个字典和实现__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

4 回答 4

4

If the inputs are not sorted, then they must all be realized (essentially, turned from an iterable into a list). You can't sort without looking at the data. LattyWare's solution is the most pythonic.

If on the other hand, the input iterables are known to be sorted, you can use heapq.merge:

>>> from heapq import merge
>>> merge(*iterables)
于 2012-05-19T15:29:50.880 回答
4

我认为您正在寻找的是链接迭代的所有值,然后对它们进行排序。为此,我们可以简单地结合itertools.chain()内置sorted()

>>> 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()'s关键功能)然后将它们链接起来。

>>> 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]

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

于 2012-05-19T15:11:06.177 回答
2

这不是zipzip将几个迭代压缩成一个可迭代的产生元组。您的功能很简单:

sorted(itertools.chain(*iterables))
于 2012-05-19T15:11:07.567 回答
0

你也可以这样做:

sorted([item for iterable in iterables for item in iterable])
于 2012-05-19T15:12:07.177 回答