def collate(*iterables, **kwargs):
    """Return an iterable ordered collation of the already-sorted items
    from each of ``iterables``, compared by kwarg ``key``.

    If ``reverse=True`` is passed, iterables must return their results in
    descending order rather than ascending.

    """
    key = kwargs.pop('key', lambda a: a)
    reverse = kwargs.pop('reverse', False)
    min_or_max = max if reverse else min

    rows = [iter(iterable) for iterable in iterables if iterable]
    next_values = {}
    by_key = []

    def gather_next_value(row, index):
        try:
            next_value = next(row)
        except StopIteration:
            pass
        else:
            next_values[index] = next_value
            by_key.append((key(next_value), index))

    for index, row in enumerate(rows):
        gather_next_value(row, index)

    while by_key:
        key_value, index = min_or_max(by_key)
        by_key.remove((key_value, index))
        next_value = next_values.pop(index)
        yield next_value
        gather_next_value(rows[index], index)
def collate ( * iterables , ** kwargs ) : key = kwargs . pop ( 'key' , lambda a : a ) reverse = kwargs . pop ( 'reverse' , False ) min_or_max = max if reverse else min rows = [ iter ( iterable ) for iterable in iterables if iterable ] next_values = { } by_key = [ ] def gather_next_value ( row , index ) : try : next_value = next ( row ) except StopIteration : pass else : next_values [ index ] = next_value by_key . append ( ( key ( next_value ) , index ) ) for index , row in enumerate ( rows ) : gather_next_value ( row , index ) while by_key : key_value , index = min_or_max ( by_key ) by_key . remove ( ( key_value , index ) ) next_value = next_values . pop ( index ) yield next_value gather_next_value ( rows [ index ] , index )
Return an iterable ordered collation of the already-sorted items
    from each of ``iterables``, compared by kwarg ``key``.

    If ``reverse=True`` is passed, iterables must return their results in
    descending order rather than ascending.