简体   繁体   中英

How can I slice a list till end with negative indexes

I learned that Python lists can also be traversed using negative index, so I tried to slice/sublist a list using negative index, but I cannot slice it till end.

My list is:

areas = ["hallway", 11.25, "kitchen", 18.0, "living room", 20.0, "bedroom", 10.75, "bathroom", 9.50]

Knowing that slicing syntax is [start:end] and end index is not calculated, I did upstairs = areas[-4:0] but this doesn't give me last element of the list.

areas[-4:0] translates to areas[len(areas) - 4: 0] , which is effectively slicing from a higher index to a lower. Semantically, this doesn't make much sense, and the result is an empty list.

You're instead looking for:

>>> areas[-4:]
['bedroom', 10.75, 'bathroom', 9.5]

When the last index is not specified, it is assumed you slice till the very end.


As an aside, specifying 0 would make sense when you slice in reverse. For example,

>>> areas[-4:0:-1]
['bedroom', 20.0, 'living room', 18.0, 'kitchen', 11.25]

Happens to be perfectly valid. Here, you slice from len(areas) - 4 down to (but not including) index 0 , in reverse.

Firstly, I wonder how you could access a slice by using areas[-4:0], it should return an empty list.

https://repl.it/repls/CarefreeOilyLine

You can use areas[-4:] which should return

> areas[-4:]
=> ['bedroom', 10.75, 'bathroom', 9.5]

Actually, you can think -4 as len(areas) - 4 like

> areas[len(areas)-4:]
=> ['bedroom', 10.75, 'bathroom', 9.5]
> areas[0:-4]
=> ['hallway', 11.25, 'kitchen', 18.0, 'living room', 20.0]
> areas[0:len(areas)-4]
=> ['hallway', 11.25, 'kitchen', 18.0, 'living room', 20.0]
> areas[0:6]
=> ['hallway', 11.25, 'kitchen', 18.0, 'living room', 20.0]

and 0 cannot represent 0 and len(areas) - 0 at the same time. Of course, it works with areas[-4:len(areas)] .

0 is not a negative number which is why it will always refer to the left-most element.

If you are hardcoding a single slice that is no problem, because you can just leave out the right boundary as in areas[-4:]

But what to do if your boundaries are computed at runtime?

>>> for left in range(-8, -3, 2):
...     right = left + 4
...     print(areas[left:right])
... 
['kitchen', 18.0, 'living room', 20.0]
['living room', 20.0, 'bedroom', 10.75]
[]

As you found out this doesn't work.

You'll often hear to just add the length of the list:

>>> for left in range(-8, -3, 2):
...     right = left + 4
...     print(areas[len(areas)+left:len(areas)+right])
... 
['kitchen', 18.0, 'living room', 20.0]
['living room', 20.0, 'bedroom', 10.75]
['bedroom', 10.75, 'bathroom', 9.5]

But that doesn't always work either:

>>> for left in range(-12, -3, 2):
...     right = left + 4
...     print(areas[len(areas)+left:len(areas)+right])
... 
[]
['hallway', 11.25, 'kitchen', 18.0]
['kitchen', 18.0, 'living room', 20.0]
['living room', 20.0, 'bedroom', 10.75]
['bedroom', 10.75, 'bathroom', 9.5]

So here is an idiom that works in a few more cases:

>>> for left in range(-12, -3, 2):
...     right = left + 4
...     print(areas[left or None:right or None])
... 
['hallway', 11.25]
['hallway', 11.25, 'kitchen', 18.0]
['kitchen', 18.0, 'living room', 20.0]
['living room', 20.0, 'bedroom', 10.75]
['bedroom', 10.75, 'bathroom', 9.5]

But you can break this as well:

>>> for left in range(-12, -1, 2):
...     right = left + 4
...     print(areas[left or None:right or None])
... 
['hallway', 11.25]
['hallway', 11.25, 'kitchen', 18.0]
['kitchen', 18.0, 'living room', 20.0]
['living room', 20.0, 'bedroom', 10.75]
['bedroom', 10.75, 'bathroom', 9.5]
[]

What do we learn from this? Negative indices are ok for hard coding but require some care when used dynamically. In a program, it may be safest to avoid negative semantics and consistently use max(0, index) .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM