This question already has answers here:
Understanding slicing
(38 answers)
Closed 6 years ago.
Suppose I was slicing a list and a string:
num_list = [1, 2, 3, 4]
print(num_list[2:]) # => [3, 4]
text_string = 'This is a test string'
print(text_string[5:] # => 'is a text string'
So, when I slice the list, the first slice index is inclusive, but when I slice the string, the slice index is noninclusive. What is it like this? Why does string slicing not follow the same ruleset that list slicing appears too?
My understanding of list slicing is that the left slice index is always inclusive, whilst the right slice index is only inclusive when it is left blank.
They both behave exactly the same.
For some reason you expect the list's indexes to start from 0 and
the string's indexes to start from 1.
The fact is that they both start at 0.
As #Mark suggested in the comments, strings and lists indexing from Python's documentation.
But it is the same!
Insert indices before each element:
[0=1,1=2,2=3,3=4][2:] means: from index 2 until end
[0=T,1=h,2=i,3=s,4= ,5=i,6=s,...][5:] means: from index 5( in this case from the letter 'i') until the end.
Related
If negative list indexing is starting from the end the list and let's say we have:
l = [1,2,3,4,5]
and l[0:3] and l[:3] returns same values while l[-3:0] returns an empty list and l[-3:] returns [3,4,5]
What is the logic behind not allowing list[-x:0] to return the list?
l[-3:0] tries to slice from 3 from behind towards 0 - that is the same as l[2:0] .. that slices nothing because the first value > second value.
l[-3:] can be read as l[-3:len(l)] - so l[2:5] which returns the slice.
You would need l[-3:0:-1] for that to work - but thats mind boggling slicing which I try to avoid. ( print( [1,2,3,4,5][-3:0:-1] --> [3, 2] ) because it also reverses the slice "orientation" to backwards instead of forwards
l[-3:] slices from 3 from behind till the end.
The full notation of slice in Python is the following:
s[start:end:step]
That being said it provides useful defaults for the values, as per the documentation:
Slice indices have useful defaults; an omitted first index defaults to
zero, an omitted second index defaults to the size of the string being
sliced.
So when you do something like:
s[1:]
under the hood this is done:
s[1:len(s)]
Note that in both cases step defaults to 1. In most languages when you want to access the last element of a list for example you do something like:
s[len(s) - 1]
Python negative indexing is a sort of syntactic sugar on that notation so :
l[-1] = l[len(l) - 1]
l[-2] = l[len(l) - 2]
...
Then when you do:
l[-3:]
this is done:
l[len(l)-3:len(l)]
So, instead of 0 you should use len(l) as the last index:
l = [1, 2, 3, 4, 5]
print(l[-3:len(l)])
Output
[3, 4, 5]
Note that l[-3:0] returns the empty list because len(l) - 3 > 0, i.e. the first index is greater than the second and step is 1.
Further
Understanding Python's slice notation
Well 0 in front works, but at last... won't work, same with this:
>>> l=[1,2,3,4,5]
>>> l[2:0]
[]
>>>
because python is thinking zero at the end...
So that's virtually equivalent to:
>>> l=[1,2,3,4,5]
>>> l[:0]
[]
>>>
since of course there is nothing before first element, if there was, that thing wouldn't be first element, it would be second.
Negative indexes operate from the end of the list.
Say if you want to get the last 3 items, you could do:
# Reversing and restoring the order
my_list = [1,2,3,4,5,6]
print(reversed(reversed(my_list)[:3]))
# Subtracting from the size
size = len(my_list)
print(my_list[size-3:])
But instead you can type
my_list[-3:]
Which in words would state get me the slice of the list starting from the third item at the end of the list
So you have to be aware of what your asking for.
# Slice from the x'th element at the end till the end of the list
my_list[-x:]
# Slice from the x'th element at the end till the y'th element at the end of the list
my_list[-x:-y]
# Slice from the x'th element at the end till the y'th element from the start of the list.
# Only valid if len(my_list) - y < x and y > 0
my_list[-x:y]
This question already has answers here:
Understanding slicing
(38 answers)
Closed 6 years ago.
For the following:
list=[[2, 3, 5], [7, 8, 9]]
Why does [list[0][0], list[1][0]] represent the first row ([2, 7]), but the command list[:][0] or list[0:2][0] returns the first column ([2, 3, 5])?
The way I see it list[:][0] should get all the possible values for the first parameter (that is 0 and 1) and 0 for the second, meaning it would return the first row. Instead what it does is return the first column and I can't understand why.
In python, the [a:b:c] syntax creates a new list. That is,
list = [1,2,3]
print(list[:])
is going to print a list, not a value.
Therefore, when you say list[:][0] you are making a copy of the original list (list[:]) and then accessing item 0 within it.
Of course you know, item 0 of the original list (list[0]) is another list.
I think you want:
[sl[0] for sl in list]
Elaboration:
This is called a "comprehension." It is a compact special syntax for generating lists, dicts, and tuples by processing or filtering other iterables. Basically {..}, [..], and (..) with an expression inside involving a for and optionally an if. Naturally, you can have multiples (like [x for x in y for y in z]) of the for, and multiples of the if.
In your case, it's pretty obvious you want a list. So []. You want to make the list by taking the first item from each sublist. So [sl[0] for sl in list].
Here's a more-detailed article: http://carlgroner.me/Python/2011/11/09/An-Introduction-to-List-Comprehensions-in-Python.html
This question already has answers here:
Understanding slicing
(38 answers)
Closed 6 years ago.
I'm a beginner attempting to learn Python. I am familiarising myself with the list data type; I've defined the following list:
>>> numbers = [1, 2, 3, 4]
Typing:
>>> numbers[0]
1
>>> numbers[1]
2
>>> numbers[2]
3
>>> numbers[3]
4
Given this, why do I get the following when I attempt to retrieve the following list elements:
>>> numbers[0:3]
[1, 2, 3]
Why isn't the list element '4' included in the response from the interpreter?
Thank you for your help.
Slice notation does not include the last element (similar to the range() function in that respect). If you want to include the last element, simply omit an index. Also, the default start is the beginning, so you don't need 0 there either:
>>> numbers[:]
[1, 2, 3, 4]
Note that this is a (shallow) copy of numbers. If you save a reference to it, you can mutate it without affecting the original numbers.
That's how slicing works in Python. To quote a tutorial:
Note how the start is always included, and the end always excluded.
This makes sure that s[:i] + s[i:] is always equal to s.
The example uses a string, but slicing works the same way with lists.
numbers[0:3] list from 0 up to 3 but 3 is excluded (like range(0,3))
This question already has answers here:
Deleting multiple elements from a list
(32 answers)
Closed 7 years ago.
I have an index of list elements that I want to delete. How can I do that ?
For example, if my original list is a=[1,2,3,4,5,6] and my index list is [2,3]. I want the elements 3,4 to be removed
Since you want to delete the indices, you can do the following two methods:
In place:
for index in sorted(indices, reversed=True):
del a[index]
out of place:
new_a = [el for index, el in enumerate(a) if index not in indices]
The reason why we sort for the in-place version is because deleting from the back doesn't modify the referenced elements in the front (note that this breaks with negative indexing).
a=[1,2,3,4,5,6]
a = a[:2] + a[4:]
print(a)
[1, 2, 5, 6]
This question already has answers here:
Why does substring slicing with index out of range work?
(3 answers)
Closed 9 years ago.
While this code will raise indexError:
In [1]: lst = [1, 2, 3]
In [2]: lst[3]
IndexError: list index out of range
Slicing the list with "out of range index" will not produce any error.
In [3]: lst[3:]
Out[3]: []
What is the rationale of this design?
When you are accessing an element in a list whose index is beyond its length, we cannot return anything. (There is no way we can represent an element which is not there). That's why the error is thrown. But when you are slicing, you are making a sliced COPY of the original list and that new list can be empty if the start or end are not valid.
It's nice being able to test if an element exists:
if sys.argv[2:]:
# do something with sys.argv[2], knowing it exists