Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python whole reverse list specifying index

Tags:

python

list

I have a list that I want to get the last few elements of in reverse order:

lst = [1,2,3,4]

I can reverse the list with lst[::-1] and get the whole list reversed. But I want the reversed list only up to a certain index. I can specify an index:

ind = 1
lst[:ind-1:-1]

and get:

[4, 3, 2]

which is the original list up to the specified index, in reverse order. This works for any index > 0. But if ind is 0 (meaning the whole list should be returned, in reverse order), this causes a problem:

ind = 0
lst[:ind-1:-1]

returns:

[]

because my ending place is the same as my beginning (-1). My expected/desired output would be [4, 3, 2, 1]

I know an easy workaround would be to just put an if statement to catch the case where ind is 0, or do it in two steps (index then reverse), but it feels like this should be doable with the indexing system in Python. Am I wrong?

like image 347
Kewl Avatar asked Mar 27 '17 19:03

Kewl


1 Answers

None can be explicitly provided to indicate "to end" (for negative step, the "end" is the beginning of the sequence):

lst[:ind - 1 if ind else None:-1]

While you did say you were avoiding the two step approach, it's frankly simpler to do it that way; unless you expect the slice to be huge, the simplicity gain is worth whatever trivial performance loss you might suffer:

lst[ind:][::-1]

For the record, on trivial microbenchmarks, assuming each ind value is equally common, the one-step approach is faster, but the difference is fairly small unless your list is huge. For example, for your four element list using ipython for microbenchmarking:

>>> lst = [1, 2, 3, 4]
>>> %%timeit -r5 inds = range(len(lst))
... for ind in inds:
...     lst[:ind-1 if ind else None:-1]
...
1000000 loops, best of 5: 791 ns per loop

>>> %%timeit -r5 inds = range(len(lst))
... for ind in inds:
...     lst[ind:][::-1]
...
1000000 loops, best of 5: 1.1 µs per loop

That's slower, but the cost is only about 300 ns. Even when lst is len 4000, the difference is 18 vs 35.5 ms per loop; granted, that's nearly doubling the time, but if it's not performance critical (or the lists are usually smaller), I'd call that acceptable, since it eases maintainer burden to read "slice from ind to end, then reverse it" rather than the more complicated structure of the one step slice.

like image 71
ShadowRanger Avatar answered Oct 18 '22 03:10

ShadowRanger