Wrapping around a list as a slice operation

Consider the following simple python code

>>> L = range(3)
>>> L
[0, 1, 2]

We can take slices of this array as follows:

>>> L[1:3]
[1, 2]

Is there any way to wrap around the above array by shifting to the left

[1, 2, 0]

by simply using slice operations?

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

Rotate left n elements (or right for negative n):

L = L[n:] + L[:n]

Note that collections.deque has support for rotations. It might be better to use that instead of lists.

Method 2

Left:

L[:1], L[1:] = L[-1:], L[:-1]

Right:

L[-1:], L[:-1] = L[:1], L[1:]

Method 3

To my mind, there’s no way, unless you agree to cut and concatenate lists as shown above.
To make the wrapping you describe you need to alter both starting and finishing index.

  • A positive starting index cuts away some of initial items.
  • A negative starting index gives you some of the tail items, cutting initial items again.
  • A positive finishing index cuts away some of the tail items.
  • A negative finishing index gives you some of the initial items, cutting tail items again.

No combination of these can provide the wrapping point where tail items are followed by initial items. So the entire thing can’t be created.

Numerous workarounds exist. See answers above, see also itertools.islice and .chain for a no-copy sequential approach if sequential access is what you need (e.g. in a loop).

Method 4

If you are not overly attached to the exact slicing syntax, you can write a function that produces the desired output including the wrapping behavior.

E.g., like this:

def wrapping_slice(lst, *args):
    return [lst[i%len(lst)] for i in range(*args)]

Example output:

>>> L = range(3)
>>> wrapping_slice(L, 1, 4)
[1, 2, 0]
>>> wrapping_slice(L, -1, 4)
[2, 0, 1, 2, 0]
>>> wrapping_slice(L, -1, 4, 2)
[2, 1, 0]

Caveat: You can’t use this on the left-hand side of a slice assignment.


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x