I have the following zip: a = zip(list_a, list_b).
It was always my understanding that once I zipped a, it would stay zipped. Such that the following would work:
for iteration in range(100):
for i, j in a:
# do something
But I noticed that on the second iteration a was empty. First of all, is my understanding of zip correct, and secondly, is there a simple single line alternative that would fit in this situation?
CodePudding user response:
zip returns an iterator; it produces each pair once, then it's done. So the solution is usually to just inline the zip in the loop so it's recreated each time:
for iteration in range(100):
for i, j in zip(list_a, list_b):
# do something
or if that doesn't work for some reason, just list-ify the zip iterator up front so it's reusable:
a = list(zip(list_a, list_b))
and then use your original looping code.
CodePudding user response:
So, in the event that you actually just want to repeat your iterator n times, but not store anything intermediate:
import itertools
def repeat_iter(iterator, n):
for it in itertools.tee(iterator, n):
yield from it
This would be more useful if you need to pass your iterator around. The nested for loop in the accepted answer is probably sufficient for most use-cases.
Usage:
In [3]: a, b = [1, 2, 3], [4, 5, 6]
In [4]: g = repeat_iter(zip(a, b), 2)
In [5]: next(g)
Out[5]: (1, 4)
In [6]: next(g)
Out[6]: (2, 5)
In [7]: next(g)
Out[7]: (3, 6)
In [8]: next(g)
Out[8]: (1, 4)
In [9]: next(g)
Out[9]: (2, 5)
In [10]: next(g)
Out[10]: (3, 6)
In [14]: next(g)
---------------------------------------------------------------------------
StopIteration Traceback (most recent call last)
<ipython-input-14-e734f8aca5ac> in <module>
----> 1 next(g)
If instead, you want to repeatedly iterate over zip(a, b) forever, you could also use itertools.cycle:
>>> c = itertools.cycle(zip(a, b))
>>> next(c)
(1, 4)
.
.
.
