Loop over list n times
Question:
Say you have this:
foo = [1,2,3,4,5,6,7,8,9,10]
bar = 22
I want to get bar
many values from foo
, repeating from the start after reaching the end. So for these inputs, the results should be 1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2
.
I have this working code:
foo = [1,2,3,4,5,6,7,8,9,10]
bar = 22
x = 0
for i in range(bar):
print(foo[x])
# increment
if x == 9:
x = 0
# back to 1
else:
x += 1
but is there a shorter way, that doesn’t use a temporary variable, x
?
Answers:
You’re probably looking for the modulo operator:
foo = [1,2,3,4,5,6,7,8,9,10]
bar = 22
for i in range(bar):
print(foo[i % len(foo)])
This will solve your question as posed, but see also 0x5453’s answer for a more general solution using itertools.
you don’t need loops at all:
foo = [1,2,3,4,5,6,7,8,9,10]
bar = 22
big_list = foo * bar #you could do this more memory efficiently by working out how many times you need to join the list based on its length.
print(list[0:bar])
Here’s the ‘memory efficient’ way of doing it, not quite as easy to decipher, you could use some helper variables to split out each part of the calculation. Having additional variables isn’t necessarily a bad thing!
foo = [1,2,3,4,5,6,7,8,9,10]
bar = 22
print(foo * (int(bar/len(foo)))+foo[0:(bar%len(foo))])
While Kemp’s solution does work, I believe a more pythonic solution is to use the itertools
package:
import itertools
foo = [1,2,3,4,5,6,7,8,9,10]
bar = 22
for i in itertools.islice(itertools.cycle(foo), bar):
print(i)
cycle
creates an endlessly repeating iterator over the specified iterable. After we consume the 10
, the iterator will be back at 1
.
islice
works like the typical list slicing syntax, but it works on iterators and generators in addition to containers. We can use that to take bar
items from the iterator.
This is a bit more flexible because it doesn’t require that foo
be subscriptable. In other words, this will work even if:
foo
is an iterator (e.g. foo = iter(foo)
)
foo
is a generator (e.g. foo = (x*2 for x in foo)
)
foo
is a special proxy object like dict_keys
or dict_values
(e.g. foo = {x: str(x) for x in foo}.keys()
)
Say you have this:
foo = [1,2,3,4,5,6,7,8,9,10]
bar = 22
I want to get bar
many values from foo
, repeating from the start after reaching the end. So for these inputs, the results should be 1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2
.
I have this working code:
foo = [1,2,3,4,5,6,7,8,9,10]
bar = 22
x = 0
for i in range(bar):
print(foo[x])
# increment
if x == 9:
x = 0
# back to 1
else:
x += 1
but is there a shorter way, that doesn’t use a temporary variable, x
?
You’re probably looking for the modulo operator:
foo = [1,2,3,4,5,6,7,8,9,10]
bar = 22
for i in range(bar):
print(foo[i % len(foo)])
This will solve your question as posed, but see also 0x5453’s answer for a more general solution using itertools.
you don’t need loops at all:
foo = [1,2,3,4,5,6,7,8,9,10]
bar = 22
big_list = foo * bar #you could do this more memory efficiently by working out how many times you need to join the list based on its length.
print(list[0:bar])
Here’s the ‘memory efficient’ way of doing it, not quite as easy to decipher, you could use some helper variables to split out each part of the calculation. Having additional variables isn’t necessarily a bad thing!
foo = [1,2,3,4,5,6,7,8,9,10]
bar = 22
print(foo * (int(bar/len(foo)))+foo[0:(bar%len(foo))])
While Kemp’s solution does work, I believe a more pythonic solution is to use the itertools
package:
import itertools
foo = [1,2,3,4,5,6,7,8,9,10]
bar = 22
for i in itertools.islice(itertools.cycle(foo), bar):
print(i)
cycle
creates an endlessly repeating iterator over the specified iterable. After we consume the 10
, the iterator will be back at 1
.
islice
works like the typical list slicing syntax, but it works on iterators and generators in addition to containers. We can use that to take bar
items from the iterator.
This is a bit more flexible because it doesn’t require that foo
be subscriptable. In other words, this will work even if:
foo
is an iterator (e.g.foo = iter(foo)
)foo
is a generator (e.g.foo = (x*2 for x in foo)
)foo
is a special proxy object likedict_keys
ordict_values
(e.g.foo = {x: str(x) for x in foo}.keys()
)