Python: make last element of array first

This is a very simple question, but I seem to be unable to find a satisfactory answer for it.

What is the best way, in Python, to make the last element of a list first by clicking on the rest of the list.

Something that does:

>>> a=[1,2,3,4] >>> a[?????] [4, 1, 2, 3] 

I know that I can always play with len , a list concatenation ...

 >>> a=[1,2,3,4] >>> [a[len(a)-1]] + a[0:len(a)-1] [4, 1, 2, 3] 

But that doesn't look right ... "Pythonic" if you can

Thanks in advance.

+6
source share
4 answers

Slicing is a little smarter than that; you can use negative indices to count from the end:

 a[-1:] + a[:-1] 

Demo:

 >>> a=[1,2,3,4] >>> a[-1:] + a[:-1] [4, 1, 2, 3] 

This works for an arbitrary number of elements that need to be brought to the fore:

 >>> a[-2:] + a[:-2] [3, 4, 1, 2] 

Using slicing like this is comparable in speed to using .insert() + .pop() (in a short list):

 >>> timeit.timeit('a[-1:] + a[:-1]', 'a=[1,2,3,4]') 0.59950494766235352 >>> timeit.timeit('a.insert(0,a.pop(-1))', 'a=[1,2,3,4]') 0.52790379524230957 

but wins hands if you need to shift more than one element:

 >>> timeit.timeit('a[-2:] + a[:-2]', 'a=[1,2,3,4]') 0.58687901496887207 >>> timeit.timeit('a.insert(0,a.pop(-1));a.insert(0,a.pop(-1))', 'a=[1,2,3,4]') 1.0615170001983643 
+12
source
 In [103]: a=[1,2,3,4] In [104]: a.insert(0,a.pop(-1)) # pop(-1) removes the last element # and use insert() to insert the popped # element at 0th endex In [105]: a Out[105]: [4, 1, 2, 3] 
+8
source

You can look at deque which are optimized (memory reasonably) to do what you ask, do a lot.

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

Since we are doing timeit for comparison ...

 >>> setup = """from collections import deque a = deque([1,2,3,4])""" >>> print timeit.timeit('a.rotate(1)', setup=setup) ... 0.219103839131 
+8
source

If you just need to drop the randomly accessible list, as you mentioned in the comment on @kreativitea, reordering may not even be necessary, and instead you can create an arbitrary access generator:

 size = 10 l = range(size) # use a generator expression to yield slices of the list according # to your own order. # note that no error checking is enforced, and that overlapping # and invalid accessRanges will work, so depending on the usage # you have for this function, you might want to add some # sanity checks, like ensuring no overlap between accessRanges # and that each item is accessed only once. def ArbitraryListAccessor(listObj, accessRanges): for ar in accessRanges: for item in listObj[ar[0]:ar[1]]: yield item # to dump the access-ordered list generator as a real list, you need to # iterate over it, for example, with a list comprehension: [i for i in ArbitraryListAccessor(l, ((-1,None), (0,-1)))] # [9, 0, 1, 2, 3, 4, 5, 6, 7, 8] 

This is slower than deque, but faster than creating new lists. For several iterations, it is about two times slower than deque, but for one run (for example, just read the list once in random order), it is compared (for example, in the order of microseconds.)

The advantage here is that you can define the random access ranges that you want to use. You can also replace ranges in functions with Slice objects and implement them like regular slices in a list (but then you will provide a fragment fragment or a slice object.)

0
source

Source: https://habr.com/ru/post/927486/


All Articles