Reputation: 59
If I have multiple iterables as argument, and is there any way to keep the code going after one of the list raise StopIteration?
I cannot use any slicing, len(), or any itertools.
This is what I have tried so far, and I know it is totally wrong but I just cannot figure this out.
def together(*args):
iterator = [iter(item) for item in args]
my_list = []
while True:
for i in iterator:
try:
lst.append(next(i))
print(next(i))
except StopIteration:
return
if '__next__' == None:
yield tuple(None)
else:
yield tuple(my_list)
my_list = []
Here is my current result, iter do store b,g,i but it only prints out first list:
[('a', 'f', 'h')]
Whats the best way to get a result like this? Resutls are tuples in a list, and when argument iterables runs out then it get replaced with Nones.
[('a', 'f', 'h'), ('b', 'g', 'i'), ('c', None, 'j'), ('d', None, 'k'), ('e', None, None)]
I know the StopIteration error rises after the ('b','g','i'), but is there any way to ignore and keep going with different list?
And input looks like:
[v for v in together(disguise('abcde'), disguise('fg'), disguise('hijk'))]
disguise function looks like:
def disguise(items):
for v in items:
yield v
Any suggestion or help will be appreciated!
Upvotes: 2
Views: 169
Reputation: 106533
You can use the second parameter of next
to let next
return a default value instead of raising a StopIteration
exception when a given iterator is exhausted:
def together(*seqs):
seqs = list(map(iter, seqs))
while True:
group = tuple(next(seq, None) for seq in seqs)
if all(i is None for i in group):
return
yield group
so that:
list(together('abcde', 'fg', 'hijk'))
returns:
[('a', 'f', 'h'), ('b', 'g', 'i'), ('c', None, 'j'), ('d', None, 'k'), ('e', None, None)]
Upvotes: 3