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)
.
.
.