5

So I want to move all the elements to the right so for example if I had a list of [1, 2, 3, 4, 5] it would become [5, 1, 2, 3, 4]. So basically the rightmost element wraps around to the leftmost element and the other elements basically shift the right.

Here is my code:

length = len(values)
old_right = values[length - 1]
for j in range(length - 1, 0, -1):
    values[j] = values[j - 1]
values[0] = old_right

When i enter it in idle i get an error on the last line on values[0] (highlighted on values) saying SyntaxError: invalid syntax. I do not know why I get this error.

Also, how would I have to change my code to make it go from [5, 4, 3, 2, 1] back to [1, 2, 3, 4, 5], i.e. reverse the process?

timgeb
  • 76,762
  • 20
  • 123
  • 145
JerryMichaels
  • 109
  • 1
  • 4
  • 9

3 Answers3

12
>>> lst = [1, 2, 3, 4, 5]
>>> [lst[-1]] + lst[:-1]
[5, 1, 2, 3, 4]

reverse:

>>> lst = [5, 1, 2, 3, 4]
>>> lst[1:] + [lst[0]]
[1, 2, 3, 4, 5]

edit:

I used [1, 2, 3, 4, 5] as an example, but i wrote the code for it to work on any list no matter what it is it would take the rightmost value of the list to the left. In your case this does work but only if you assign the specific list. I am wondering how would you do it so it works any general case.

Then write a function.

def shift_right(lst):
    try:
        return [lst[-1]] + lst[:-1]
    except IndexError:
        return lst
timgeb
  • 76,762
  • 20
  • 123
  • 145
8

Use the deque module.

from collections import deque
a = deque([1,2,3,4,5]).rotate(1)

a = list(a)

This is the ideal solution since it lets you rotate the list an arbitrary number of places. If you want to rotate it the other way, you can make the argument to rotate negative.

EDIT:

The currently accepted answer is much slower than this approach. The deque data structure is optimized for inserting at the beginning of the list and the end of the list, which is much faster than the linear time operation of the accepted answer. This may not matter in the context for which the OP is using the code, but in any context where performance matters, deque is the way to go.

I wrote a small program that rotates a list of 1,000,000 elements by one position 1,000 times. Here are the results

List Slicing: 0:00:12.043186
Deque: 0:00:00.028064

Code is here.

import datetime
from collections import deque


start = datetime.datetime.now()

lst = [1]* 1000000

#first approach
for x in range(1000):
    lst = [lst[-1]] + lst[:-1]

end  = datetime.datetime.now()
print end - start

lst = deque(lst)
#second approach 
for y in range(1000):
    lst.rotate(1)
lst = list(lst)

start = datetime.datetime.now()
print start - end
Erik Godard
  • 5,930
  • 6
  • 30
  • 33
  • I wouldnt consider this the idea situation because you can do the same thing with a list slice, arbitrary number of places and all, and not have to do an import and/or cast the deque object as a list. – R Nar Dec 15 '15 at 00:35
  • @RNar, if the op is doing this a lot then using a deque will be much more efficient. This is constant work as opposed to a linear approach in the first answer. – Padraic Cunningham Dec 15 '15 at 00:39
  • good point. wondering if the list conversion would still be constant work? – R Nar Dec 15 '15 at 00:42
  • What exactly would deque do? – JerryMichaels Dec 15 '15 at 00:43
  • @RNar, I meant more in the sense that the OP should switch to a deque altogether if possible. Even if they have to cast once the shift back would still make it more efficient than the list slicing – Padraic Cunningham Dec 15 '15 at 00:44
  • In short, when working with slices you have to create new list to make it be what you want. deque.rotate() does it by using the data structure property (resetting pointers). Obviously it is more efficient than shifting elements around. And, no, why would anyone transform deque() back to list when it can be used as is, nearly like a list. Only if algorithm requires some list specific properties that deque cannot offer, like random memory access. +1 for this answer although deque() is not a module :D. Just a little data structure class. – Dalen Dec 15 '15 at 00:48
  • What deque() does? To shorten the explanation, it is implemented as a double-linked list. Ideal to use as a FIFO. It supports most of standard list features. – Dalen Dec 15 '15 at 00:55
  • Speed for me isn't the concern, it is to simply get the matter done. I appreciate the great explanation but i find it a little bit more confusing whereas the accepted answer is concise. – JerryMichaels Dec 15 '15 at 00:56
  • 1
    @erik, you might find the time it lib to be a bit better for timing code than the date time module – Padraic Cunningham Dec 15 '15 at 00:57
  • `deque` could be a great solution but it takes up more memory, takes longer to build in the first place and doesn't do other listy things like random access. It all depends on what else OP plans to do with the list. – tdelaney Dec 15 '15 at 01:18
2
a = [1,2,3,4,5]
x = a.pop()
a.insert(0, x)
xuhdev
  • 8,018
  • 2
  • 41
  • 69
  • This is faster than slicing. – tdelaney Dec 15 '15 at 01:03
  • This also mutates the original list – Padraic Cunningham Dec 15 '15 at 01:04
  • @PadraicCunningham It does and skipping the need for reallocating the list is part of the speed. Even though the original question doesn't have a requirement either way, its example shows an update in place. – tdelaney Dec 15 '15 at 01:11
  • @Dalen - `timeit` tells me this is 20 times faster on a million member list. What did your measurements tell you? – tdelaney Dec 15 '15 at 01:12
  • @tdelaney, yes, this would definitely be the preferable way if you were not going to use a deque – Padraic Cunningham Dec 15 '15 at 01:12
  • but list.insert() forces all elements after wanted index to be shifted right, thus doing malloc again. Sometimes whole list have to be copied. I agree that this is the right way if not using deque(). – Dalen Dec 15 '15 at 01:39
  • @Dalen It is not `malloc`, it would be `realloc`. – xuhdev Dec 15 '15 at 01:41
  • It is immaterial which one it is, the effect is same or nearly so, and please don't start a discussion about how and when and where because we will never stop. To be 100% sure how it is done, we would have to look at CPython code. But, yeah, realloc() most probably. Happy now? – Dalen Dec 15 '15 at 01:48
  • @Dalen `realloc` would not lead to your the inefficiency, because `realloc` is different from `malloc` in terms of efficiency, which makes the point. – xuhdev Dec 15 '15 at 01:56
  • Yes, yes, of course, but it also depends on OS etc. etc. and you still have to manually shift all elements and there is a chance that it will act like a malloc() and then copy the data on new location. Unless OS does some magic (not Windows :D ) to avoid this. See: http://www.cplusplus.com/reference/cstdlib/realloc/ So it can be more efficient or less efficient depending on case. I think that is enough. OP really didn't ask on how list is implemented. Sorry. – Dalen Dec 15 '15 at 02:27