Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Loop over list n times [duplicate]

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?


2 Answers

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())
like image 155
0x5453 Avatar answered Dec 07 '25 19:12

0x5453


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.

like image 27
Kemp Avatar answered Dec 07 '25 17:12

Kemp