Выход из отсортированных итераторов в отсортированном порядке в Python? - PullRequest
10 голосов
/ 03 августа 2011

Есть ли лучший способ объединить / отсортировать несколько отсортированных итераторов в один, чтобы получить элементы в отсортированном порядке?Я думаю, что приведенный ниже код работает, но я чувствую, что есть более чистый, более краткий способ сделать это, которого мне не хватает.

def sortIters(*iterables, **kwargs):
    key = kwargs.get('key', lambda x : x)
    nextElems = {}
    currentKey = None
    for g in iterables:
        try:
            nextElems[g] = g.next()
            k = key(nextElems[g])
            if currentKey is None or k < currentKey:
                currentKey = k
        except StopIteration:
            pass #iterator was empty
    while nextElems:
        minKey = None
        stoppedIters = set()
        for g, item in nextElems.iteritems():
            k = key(item)
            if k == currentKey:
                yield item
                try:
                    nextElems[g] = g.next()
                except StopIteration:
                    stoppedIters.add(g)
            minKey = k if minKey is None else min(k, minKey)
        currentKey = minKey
        for g in stoppedIters:
            del nextElems[g]

Вариант использования для этого, что у меня есть куча файлов CSVчто мне нужно объединить согласно некоторому отсортированному полю.Они достаточно большие, поэтому я не хочу просто читать их все в списке и вызывать sort ().Я использую python2.6, но если есть решение для python3, мне все равно было бы интересно его увидеть.

1 Ответ

25 голосов
/ 03 августа 2011

да, вы хотите heapq.merge(), что делает ровно одну вещь; перебрать отсортированные итераторы в порядке

def sortkey(row):
    return (row[5], row)

def unwrap(key):
    sortkey, row = key
    return row

from itertools import imap
FILE_LIST = map(file, ['foo.csv', 'bar.csv'])
input_iters = imap(sortkey, map(csv.csvreader, FILE_LIST))
output_iter = imap(unwrap, heapq.merge(*input_iters))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...