Yes, calling s[0:-1] is exactly the same as calling s[:-1].
Using a negative number as an index in python returns the nth element from the right-hand side of the list (as opposed to the usual left-hand side).
so if you have a list as so:
myList = ['a', 'b', 'c', 'd', 'e']
print myList[-1] # prints 'e'
the print statement will print "e".
Once you understand that (which you may already, it's not entirely clear if that's one of the things you're confused about or not) we can start talking about slicing.
I'm going to assume you understand the basics of a slice along the lines of myList[2:4] (which will return ['c', 'd']) and jump straight into the slicing notation where one side is left blank.
As you suspected in your post, myList[:index] is exactly the same as myList[0:index].
This is also works the other way around, by the way... myList[index:] is the same as myList[index:len(myList)] and will return a list of all the elements from the list starting at index and going till the end (e.g. print myList[2:] will print ['c', 'd', 'e']).
As a third note, you can even do print myList[:] where no index is indicated, which will basically return a copy of the entire list (equivalent to myList[0:len(myList)], returns ['a', 'b', 'c', 'd', 'e']). This might be useful if you think myList is going to change at some point but you want to keep a copy of it in its current state.
If you're not already doing it I find just messing around in a Python interpreter a whole bunch a big help towards understanding these things. I recommend IPython.
Answer from Redwood on Stack OverflowList slicing with negative index
Negative zero (-0) as a slice index - Ideas - Discussions on Python.org
Negative Slicing in Python
Negative slicing Python
Yes, calling s[0:-1] is exactly the same as calling s[:-1].
Using a negative number as an index in python returns the nth element from the right-hand side of the list (as opposed to the usual left-hand side).
so if you have a list as so:
myList = ['a', 'b', 'c', 'd', 'e']
print myList[-1] # prints 'e'
the print statement will print "e".
Once you understand that (which you may already, it's not entirely clear if that's one of the things you're confused about or not) we can start talking about slicing.
I'm going to assume you understand the basics of a slice along the lines of myList[2:4] (which will return ['c', 'd']) and jump straight into the slicing notation where one side is left blank.
As you suspected in your post, myList[:index] is exactly the same as myList[0:index].
This is also works the other way around, by the way... myList[index:] is the same as myList[index:len(myList)] and will return a list of all the elements from the list starting at index and going till the end (e.g. print myList[2:] will print ['c', 'd', 'e']).
As a third note, you can even do print myList[:] where no index is indicated, which will basically return a copy of the entire list (equivalent to myList[0:len(myList)], returns ['a', 'b', 'c', 'd', 'e']). This might be useful if you think myList is going to change at some point but you want to keep a copy of it in its current state.
If you're not already doing it I find just messing around in a Python interpreter a whole bunch a big help towards understanding these things. I recommend IPython.
>>> l = ['abc', 'def', 'ghi', 'jkl', 'mno', 'pqr', 'stu', 'vwx', 'yz&']
# I want a string up to 'def' from 'vwx', all in between
# from 'vwx' so -2;to 'def' just before 'abc' so -9; backwards all so -1.
>>> l[-2:-9:-1]
['vwx', 'stu', 'pqr', 'mno', 'jkl', 'ghi', 'def']
# For the same 'vwx' 7 to 'def' just before 'abc' 0, backwards all -1
>>> l[7:0:-1]
['vwx', 'stu', 'pqr', 'mno', 'jkl', 'ghi', 'def']
Please do not become listless about list.
- Write the first element first. You can use positive or negative index for that. I am lazy so I use positive, one stroke less (below 7, or -3 for the start).
- Index of the element just before where you want to stop. Again, you can use positive or negative index for that (below 2 or -8 for stop).
Here sign matters; of course - for backwards; value of stride you know. Stride is a 'vector' with both magnitude and direction (below -1, backwards all).
l = [0,1,2,3,4,5,6,7,8,9] l[7:2:-1], l[-3:2:-1], [-3:-8:-1],l[7:-8:-1]All result in
[7, 6, 5, 4, 3].
Although I know how slicing works but following examples kind of stumped me.
values = [3,4,3,7,8,9,5] values[:3:-1] #o/p [5,9,8] values[5:3:-1] #o/p [9,8]
I always thought in list[start:stop:step], 'start' defaults to 0, 'stop' defaults to length-1 and 'step' defaults to 1. But this doesn't make sense here. What are the rules? Link to official docs will also be appreciated as I couldn't find that.
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.
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 farthest right you can specify with a negative index is -1, which refers to the final item in a sequence. However, slice semantics are that the index following the : is excluded from the slice.
Therefore, there is no way, using a negative index to the right of the :, to include the final item in a list.
You could "fix" this in your function by replacing -i with -i if i else len(arr):
def find_even_index(arr):
for i in range(len(arr)):
print(arr[-(len(arr)):-i if i else len(arr)])
find_even_index([1,2,3,4,3,2,1])
Output:
[1, 2, 3, 4, 3, 2, 1]
[1, 2, 3, 4, 3, 2]
[1, 2, 3, 4, 3]
[1, 2, 3, 4]
[1, 2, 3]
[1, 2]
[1]
Working:
def find_even_index(arr):
for i in range(len(arr)):
print(arr[:len(arr) - i])
find_even_index([1,2,3,4,3,2,1])
#prints:
[1, 2, 3, 4, 3, 2, 1]
[1, 2, 3, 4, 3, 2]
[1, 2, 3, 4, 3]
[1, 2, 3, 4]
[1, 2, 3]
[1, 2]
[1]
When you had
arr[:-i]
i started at 1, so you told it, in essence, to do
arr[0:-0]
# which is
arr[0:0]
Which is what caused it to print nothing. instead, start at the length of the array and incrementally subtract 1.