-1

Title may be confusing but I don't know how to express myself any better. What I have is a list that looks something like this:

myList = ['a', 'b', 'c', 'd', 'e', 'f']

what I want to do is a for loop that, for example, starts at index 3, so 'd' and then goes to the end but at the end of the list insted of finishing goes back to the beginning, goes through 'a','b','c' and then finishes at 'd'. I tried doing it like this with a while loop:

index = 3
while index != 2:
    if index == len(a):
        index = 0
    else:
        pass
    print(a[index])
    index += 1

This sorta worked but it will never print out 'c' but if I put 3 as index the loop will never even start. Is there a more elegant solution to do something like this?

OneCricketeer
  • 179,855
  • 19
  • 132
  • 245
WholesomeGhost
  • 1,101
  • 2
  • 17
  • 31

4 Answers4

9

You can use the modulus operator against the length of the string

def offset_print(s, offset):
    for i in range(len(s)):
        print(s[(i+offset) % len(s)])

Example

>>> offset_print('hello', 2)
l
l
o
h
e
Cory Kramer
  • 114,268
  • 16
  • 167
  • 218
2

So, definitely like @CoryKramer's approach, but this one doesn't require you to calculate the length of the iterator:

def run_offset(lst, fn, offset=0):
    base = []
    for item in lst:
      if offset > 0:
        # append the original list until you're no longer dealing with an offset
        base.append(item)
        offset -= 1
        continue

      # just yield the current value
      yield item

    # iterate through the indexes 0... offset
    for item in base:
      yield item

> list(run_offset('abcd', print, 2))
['c', 'd', 'a', 'b']
cwallenpoole
  • 79,954
  • 26
  • 128
  • 166
2

Not the most efficient -- but if your list is short and you just want pure simplicity, you can shift your list;

shifted = my_list[n:] + my_list[:n]
for item in shifted:
    # do stuff here

... Or use a deque;

>>> import collections
>>> dq = collections.deque(['a', 'b', 'c', 'd'])
>>> dq
deque(['a', 'b', 'c', 'd'])
>>> dq.rotate(2)
>>> dq
deque(['c', 'd', 'a', 'b'])
SteveJ
  • 3,034
  • 2
  • 27
  • 47
1

Using itertools.cycle also works here:

from itertools import cycle

def offset_print(s, offset):
    it = cycle(s)

    items = [next(it) for i in range(len(s) + offset)]

    for x in items[offset:]:
        print(x)

Which Outputs:

>>> offset_print(['a', 'b', 'c', 'd', 'e', 'f'], 2)
c
d
e
f
a
b
RoadRunner
  • 25,803
  • 6
  • 42
  • 75