2

I have a list and I want to iterate through it from element 1 to the end, and then finish up with element 0. Ie, essentially it's basic list iteration, except the very first element should be at the end.

I could do this with for i in range(len(myList)): and then adding 1 to i and checking for the edge case (that 's how I'd do in it C++), but was wondering if Python had some syntax which would make this concept easier to express?

3
  • 7
    for i in list[1:] + list[:1]: Commented Feb 12, 2021 at 2:59
  • @PacketLoss, IMHO it's the best answer - why don't to convert it to a regular answer and gain reputation points for it? Commented Feb 12, 2021 at 3:25
  • @kitfox a modulo operator can be handy in such situations, and the concept remains same in other languages. I've added as answer. Hope it adds some more value. Commented Feb 12, 2021 at 3:26

4 Answers 4

5

I don't believe there is a convenient syntax for this, but you could easily define your own: I've chosen the name irotate by analogy to itertools.islice, and written it in a way such that it can be provided a single-use iterable such as a generator expression.

def irotate(iterable, k=1):
    iterator = iter(iterable)
    initial_elements = [next(iterator) for _ in range(k)]
    yield from iterator
    yield from initial_elements

Example usage:

>>> list(irotate(range(5)))
[1, 2, 3, 4, 0]
>>> for x in irotate(y**2 for y in range(5)): print(x)
... 
1
4
9
16
0
Sign up to request clarification or add additional context in comments.

5 Comments

I would just replace [next(iterator) for _ in range(k)] with just list(islice(iterator, k))
Curiously, what is the argument for simply not using slicing for this? Noting both answers did not mention the simplicity of using sliced notation to achieve this. Is there a specific reason a method like the ones provided should be used over slicing?
@PacketLoss If it's a list then you can use slicing, sure; however, this way works with O(k) auxiliary space instead of O(n), and works when the iterable is not a list or tuple.
@kaya3 Perfect, thank you for expanding on the answer. +1
@PacketLoss Since your comment does answer the question in a simpler way, though, I suggest you convert it to an answer.
3

The most simple way to achieve this, without the need for error handling/checks is to just use slicing.

_list = [1, 2, 3, 4]

for i in _list[1:] + _list[:1]: 
    print(i)

#2
#3
#4
#1

Comments

2

... and then adding 1 to i and checking for the edge case ...

If you want only get rid of the checking for the edge case, use cycle() from the itertools standard module to create an infinite iterator:

import itertools

my_list = [2, 10, "a"]
my_iter = itertools.cycle(my_list)   # 2, 10, "a", 2, 10, "a", 2, 10, "a", ...

next(my_iter)                        # drop the first element
for __ in range(len(my_list)):
    curr_elem = next(my_iter)
    print(curr_elem)                 # or do other activity with the current element

The output:

10
a
2

Comments

1

One could use modulo to get something like this -

mylist = [i for i in range(8)]
for i in range(5):
  diff = i
  rotated = [mylist[i % len(mylist)] for i in range(diff, len(mylist)+diff)]
  print(rotated)

Output is -

[0, 1, 2, 3, 4, 5, 6, 7]
[1, 2, 3, 4, 5, 6, 7, 0]
[2, 3, 4, 5, 6, 7, 0, 1]
[3, 4, 5, 6, 7, 0, 1, 2]
[4, 5, 6, 7, 0, 1, 2, 3]

It is creating another list. So, may wanna keep that in mind.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.