How do I merge two python iterators?

前端 未结 13 1267
花落未央
花落未央 2020-12-06 09:29

I have two iterators, a list and an itertools.count object (i.e. an infinite value generator). I would like to merge these two into a resulting ite

13条回答
  •  天涯浪人
    2020-12-06 09:54

    Here is an elegant solution:

    def alternate(*iterators):
        while len(iterators) > 0:
            try:
                yield next(iterators[0])
                # Move this iterator to the back of the queue
                iterators = iterators[1:] + iterators[:1]
            except StopIteration:
                # Remove this iterator from the queue completely
                iterators = iterators[1:]
    

    Using an actual queue for better performance (as suggested by David):

    from collections import deque
    
    def alternate(*iterators):
        queue = deque(iterators)
        while len(queue) > 0:
            iterator = queue.popleft()
            try:
                yield next(iterator)
                queue.append(iterator)
            except StopIteration:
                pass
    

    It works even when some iterators are finite and others are infinite:

    from itertools import count
    
    for n in alternate(count(), iter(range(3)), count(100)):
        input(n)
    

    Prints:

    0
    0
    100
    1
    1
    101
    2
    2
    102
    3
    103
    4
    104
    5
    105
    6
    106
    

    It also correctly stops if/when all iterators have been exhausted.

    If you want to handle non-iterator iterables, like lists, you can use

    def alternate(*iterables):
        queue = deque(map(iter, iterables))
        ...
    

提交回复
热议问题