I'd like to combine two iterators and yield the value(s) of the iterator that has the highest timestamp.
Minimal example and expectations:
# Outputs of these generators are "timestamps"
def gen_even():
    for x in range(0, 11, 2):
        yield x
        
def gen_odd():
    for x in sorted(list(range(1, 15, 2)) + [6]):
        yield x
Combining these two should result in in the following sequence
[0, 1, 2, 3, 4, 5, (6, 6), 7, 8, 9, 10, 11, 13]
I tried the following which runs into StopIteration after gen1 has been consumed.
gen1 = gen_even()
gen2 = gen_odd()
def gen_both(gen1, gen2):
    first = next(gen1)
    second = next(gen2)
    
    while True:   
        if first < second:
            yield first
            first = next(gen1)
        elif first == second:  
            yield first, second
            first = next(gen1)
            second = next(gen2)            
        else:
            yield second
            second = next(gen2)
gen = gen_both(gen1, gen2)
for i in gen:
    print(i)
Output:
0
1
2
3
4
5
(6, 6)
7
8
9
10
---------------------------------------------------------------------------
StopIteration                             Traceback (most recent call last)
Cell In[8], line 11, in gen_both(gen1, gen2)
     10     yield first
---> 11     first = next(gen1)
     12 elif first == second:  
StopIteration: 
The above exception was the direct cause of the following exception:
RuntimeError                              Traceback (most recent call last)
Cell In[8], line 21
     18             second = next(gen2)
     20 gen = gen_both(gen1, gen2)
---> 21 for i in gen:
     22     print(i)
RuntimeError: generator raised StopIteration
How can I do this in Python?
You could avoid the stop iterator by handling it as follows:
def gen_both(gen1, gen2):
    first = next(gen1, None)
    second = next(gen2, None)
    
    while True:
        if first is None and second is None:
            break
        elif first is None:
            yield second
            second = next(gen2, None)
        elif second is None:
            yield first
            first = next(gen1, None)
        else:
            if first < second:
                yield first
                first = next(gen1, None)
            elif first == second:  
                yield first, second
                first = next(gen1, None)
                second = next(gen2, None)            
            else:
                yield second
                second = next(gen2, None)
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With