This question already has answers here:
Understanding slicing
(38 answers)
Closed 2 months ago.
the range function has syntax range(start,stop,step) and returns a sequence based on the arguments. Please explain the syntax range(10)[2:6][2]
range(10) is identical to range(0,10,0). what is happening with '[2:6][2]?
thanks
entering range(10)[2:6][2] evaluates to 4, but I don't understand why.
range(param) is a build-function that generate a list. The param is the lenght of number of list.
So you have a list of 10 numbers. From 0 to 9. Remenber arrays become at the 0 position.
Then you slice the list with [start,end, jumps]. You slice the list.
The result is 2,3,4,5.
After that you call the number at position [2].
Beginning from 0 => 2
Next position 1 => 3
Then position 2 => 4
The range function in Python has the syntax range(start, stop, step) and generates a sequence of numbers starting from start, up to but not including stop, with a step size of step. In the case of range(10), this generates a sequence of numbers starting from 0 and up to but not including 10, with a step size of 1. Note that the default value for the start parameter is 0 and the default value for the step parameter is 1, so range(10) is is identical to range(0,10,1) rather than range(0,10,0) as you indicated in your post.
You can find documentation for the range built-in function at: http://docs.python.org/3/library/functions.html#func-range and https://docs.python.org/3/library/stdtypes.html#typesseq-range
The square brackets after the range function are used to index the resulting sequence. For example, range(10)[2:6] returns a sub-sequence of numbers starting from the 3rd element (index 2) and up to but not including the 6th element (index 5), which in this case is [2, 3, 4, 5].
The second set of square brackets then indexes this sub-sequence, returning the 3rd element. Therefore, the expression range you provided evaluates to 4.
You can find documentation for the slicing syntax at: https://python-reference.readthedocs.io/en/latest/docs/brackets/slicing.html
Related
This question already has answers here:
Understanding slicing
(38 answers)
Closed 4 years ago.
Hay fellow programmers,
I'm new to programming and was wondering if someone could help clear something up for me? I'm not sure if it's because of the way it's written or if it is simply a real, but contradictory way of doing something.
I'm currently learning Python from the book 'Learn Python in One Day' and their explanation of list slicing has confused me. At the beginning, they state individual indexes always start from zero, but in a later example they seem to be using '1' as the starting point(?) and ending at index 5 - 1?
The example they're using for below is: userAge = [21, 22, 23, 24, 25]
At the beginning, in the extract below, they explain that the index for 21 = 0, the index for 22 = 1, 23 = 2, 24 = 3, and 25 = 4.
But when they get to the bottom of the extract they are talking about a 5th index (despite there not being one in the example above)...
Here's the extract from the book. I've highlighted the bits that have confusticated me:
"Individual values in the list are accessible by their indexes, and indexes always start from ZERO, not 1. This is a common practice in almost all programming languages, such as C and Java. Hence the first value has an index of 0, the next has an index of 1 and so forth. For instance, userAge[0] = 21, userAge[1] = 22.
Alternatively, you can access the values of a list from the back. The last item in the list has an index of -1, the second last has an index of -2 and so forth. Hence, userAge[-1] = 25, userAge[-2] = 24.
You can assign a list, or part of it, to a variable. If you write userAge2 = userAge, the variable userAge2 becomes [21, 22, 23, 24, 25].
If you write userAge3 = userAge[2:4], you are assigning items with index 2 to index 4-1 from the list userAge to the list userAge3. In other words, userAge3 = [23, 24].
The notation 2:4 is known as a slice. Whenever we use the slice notation in Python, the item at the start index is always included, but the item at the end is always excluded. Hence the notation 2:4 refers to items from index 2 to index 4-1 (i.e. index 3), which is why userAge3 = [23, 24] and not [23, 24, 25].
The slice notation includes a third number known as the stepper. If we write userAge4 = userAge[1:5:2], we will get a sub list consisting of every second number from index 1 to index 5-1 because the stepper is 2. Hence, userAge4 = [22, 24].
In addition, slice notations have useful defaults. The default for the first number is zero, and the default for the second number is size of the list being sliced. For instance, userAge[ :4] gives you values from index 0 to index 4-1 while userAge[1: ] gives you values from index 1 to index 5-1 (since the size of userAge is 5, i.e. userAge has 5 items)."
I'm not sure where they are getting the '5 - 1' if the original example had only index 0 - 4 (despite that meaning there are five items in the list). Is this a "rule change" or have they changed the index numbers from 0 to 4, to 1 to 5? I know the '5 - 1' means you would go back to index 4 due to the "end exclusive" they mention above, but don't you need the item there before you can minus it? In the original example, there is no 5th index (though there are 5 items on the list)...
Needless to say, I am very confused! Haha.
Thanks in advance for your help!
Jane. x
Well, there's quite a lot of misleading explanations in this extract.
Regarding default values for slicing – forget the indexes, in "human" interpretation:
data[x:] – slice starting from index x all the way till the end
data[:x] – slice starting from the very beginning and up to x-th element
Reason reason they're telling about 5 - 1 is because second value for slicing is exclusive, i.e. to explicitly slice till the end of array of length N, you're writing [:N], but last element will have index N-1 – exactly because indexing starts at 0, but element count starts from 1.
When slicing userAge[1:], you get everything from the 2nd element all the way to the last one.
userAge[1:] = [22, 23, 24, 25]
Slicing can be explained like this.
a[first:last]#items goes at first to last-1
a[first:]#items goes from first to the rest of the array
a[:last]#items from the beginning to the end-1
a[:]#copy of the whole array.
For Step
a[first:last:step]#starts from first, not past last,by step.
I will give you another example, if you ask for a[:-2] and an only contains one element, you get an empty list instead of an error.
So, in this when we use `userage[1:], everything starts from 2nd element.
This question already has answers here:
Understanding slicing
(38 answers)
Closed 5 years ago.
I've seen a few questions about copying parts from Arrays or list, but I still don't understand the logic behind it... It makes no sense for me that I can get each values by calling them by index, but it is not possible to get a part of the list by calling it by index, too...
x=[0,1,2,3,4,5]
>>>x[2]
2
>>>x[4]
4
>>>x[2:4]
[2,3]
What I am expecting in the last line would be that the command returns the value with index two,three and four !
>>> x[2:4]
[2,3,4]
Is there a command that does it the way I thought it would be?
You are missing that x[2:4] gets all values where the index is 2 <= index < 4. Therefore, you get index 2 and 3, but not 4. This is done so that you can always tell the size of a partial list (not just in python but in computing in general) by subtracting the upper bound by the lower bound. 4 - 2 = 2, therefore the list has two items in it.
There is an interesting piece of writing by E.W. Dijkstra about this if you care to read it here.
The operation that you are performing :
x[2:4]
is called the slicing operation. The format of it such that, for a list[x:y] you get the values in index from the range x to y-1. ie, list[x]...list[y-1]
Hence, when you do x[2:4] , you will get the values from
x[2]...x[4-1] => x[2]...x[3]
Hence you have for :
>>> x = [0,1,2,3,4,5]
>>> x[2:4]
=> [2, 3]
#should be
>>> x[2:5]
=> [2, 3, 4]
A few reading references :
How to Slice Lists/Arrays and Tuples in Python
Understanding
Python's slice notation
You can do
x[2:5]
Because writing x[a:b]starts from index a up to and not including index b
So in your case you needed x[a:b+1]
This question already has answers here:
Understanding slicing
(38 answers)
Closed 4 years ago.
I cannot understand this. I have seen this in people's code. But cannot figure out what it does. This is in Python.
str(int(a[::-1]))
Assuming a is a string. The Slice notation in python has the syntax -
list[<start>:<stop>:<step>]
So, when you do a[::-1], it starts from the end towards the first taking each element. So it reverses a. This is applicable for lists/tuples as well.
Example -
>>> a = '1234'
>>> a[::-1]
'4321'
Then you convert it to int and then back to string (Though not sure why you do that) , that just gives you back the string.
The notation that is used in
a[::-1]
means that for a given string/list/tuple, you can slice the said object using the format
<object_name>[<start_index>, <stop_index>, <step>]
This means that the object is going to slice every "step" index from the given start index, till the stop index (excluding the stop index) and return it to you.
In case the start index or stop index is missing, it takes up the default value as the start index and stop index of the given string/list/tuple. If the step is left blank, then it takes the default value of 1 i.e it goes through each index.
So,
a = '1234'
print a[::2]
would print
13
Now the indexing here and also the step count, support negative numbers. So, if you give a -1 index, it translates to len(a)-1 index. And if you give -x as the step count, then it would step every x'th value from the start index, till the stop index in the reverse direction. For example
a = '1234'
print a[3:0:-1]
This would return
432
Note, that it doesn't return 4321 because, the stop index is not included.
Now in your case,
str(int(a[::-1]))
would just reverse a given integer, that is stored in a string, and then convert it back to a string
i.e "1234" -> "4321" -> 4321 -> "4321"
If what you are trying to do is just reverse the given string, then simply a[::-1] would work .
I've a list say, sample_list = [1,2,3,4,5,6,7].
Now, when I try to access:
print(sample_list[-2:2])
or,
print(sample_list[-3:-7])
In both cases, I get an empty list.
Should not it print at-least [6,7] or [5,6,7] respectively, following left-to-right convention?
I know, I'm doing something wrong semantic-wise.
(trying to print the list in right-to-left direction?)
I would like to understand the logic behind empty list. What is happening here?
If you want to slice from right to left, you need to provide a negative step: sample_list[-2:2:-1]. This will also reverse the order of the values.
And a slice like [-2:2] isn't meaningless. If you do sample_list[-2:2] on a list of length two, you'd get a copy of the whole thing. In a list of length three, you'll get a slice with only the middle element. It's only for lists of length 4 or larger, you get an empty slice. If they reversed themselves automatically, then some of those cases would be ambiguous.
Edit: Let me try to make a more comprehensive explanation.
Python's slice syntax is implemented by slice objects. That is, L[start:stop:step] is equivalent to L[slice(start, stop, step)]. (Well, this is how it works in Python 3. For backwards compatibility reasons Python 2 also has an older approach, using __getslice__ and __setslice__ methods, but the newer way with slice objects works too.)
When you take a slice or a list or tuple, you always get elements starting with the index start and continuing up until the element just before stop. The step parameter describes the size of the steps taken, with 2 meaning every other value, and -1 meaning steps in reverse.
Another way of thinking of it is that a slice L[start:stop:step] is almost equivalent to the list comprehension [L[i] for i in range(start, stop, step)]. The differences are only in what happens when some of the values are negative or not provided.
The rule for handling negative values is easy (and it's the same as for non-slice indexing). For start and stop, just add the length of the sequence to any negative value. So, for positive x and y, the slice L[-x:-y] is exactly equivalent to L[len(L)-x:len(L)-y]. Negative step values don't get transformed.
Unlike regular indexing, slicing never raises exceptions for indexes out of range. If indexes are invalid, you may get an empty result, or just fewer values than the slice was asking for.
Not all arguments to a slice are required. A slice object's constructor assigns None as default values for any argument not provided. What those Nones mean for start and stop differs depending on the sign of step, and also on the dimensions of the list that's being sliced.
If step is None it is always treated as if it was 1. If step is positive (or None), a start value of None is treated as if it was 0 and a stop value of None is treated like len(L). If step is negative, a start value of None is treated as -1 and stop value of None is treated as -len(L)-1.
So, to circle back to your question, when you do the slice sample_list[-2:2], several things happen:
First off, a slice object is created, as if you did slice(-2, 2). That slice object will have a step of None, since you didn't provide a third value.
Next, the slice is passed to the list and the values are interpreted. Since step was None, the default of 1 is used. Since start is negative, the length of the list is added to it.
Finally, the results are figured out. For your example list with seven values, you get the equivalent of [sample_list[i] for i in range(5, 2, 1)]. Since the range is empty, the slice is too.
Depending on what you wanted, you can fix this in a few different ways. You could leave it be and you'll get results only for very short source lists, where len(L)-2 is less than 2. Alternately, you could swap the order of your first two arguments, and get the result [3,4,5]. Or you could add a negative step and slice from right to left, resulting in [6, 5, 4].
Remember that indexes start at 0:
sample_list = [1,2,3,4,5,6,7]
# 0 1 2 3 4 5 6
When you do sample_list[-2:2], you're trying to get the second last element to the third element.
But you can't just go from negative to positive (unless you add in a negative step). If you wish to obtain a reversed list, then add a step:
>>> print sample_list[2:-2][::-1]
[5, 4, 3]
This is the same problem with your second example. You're trying to go backwards with negative indicies, but you can't... unless... you add in a negative step!:
>>> print sample_list[-3:-7:-1]
[5, 4, 3, 2]
This question already has answers here:
Understanding slicing
(38 answers)
Closed 9 years ago.
#!/usr/bin/python
list2 = ['Bangalore','Cochin','Trivandrum','Auckland','Seoul','Los Angeles']
list2[5] = 'Hamilton'
list2.append('Sydney')
list2.append('San Jose')
list2.append('Amsterdam')
print "Cities = ",list2[0:(len(list2) - 1)]
print "Cities = ",list2[0:(len(list2))]
The first print statement does not print the last element in the list.The second print statement does print all the elements in the list without an out of bounds errors.From the documentation I understand len() simply returns the number of elements in the list.Then why is the last index not len(list) - 1
List slicing never throws an out-of-bounds error:
list2[0:1234567890]
is legal, as is
list2[-1:-1]
Note that when slicing, the upper bound is not included in the slice:
>>> list2[0:1]
['Bangalore']
>>> list2[0:0]
[]
so the slice list2[0:len(list2)] contains exactly the same elements as list2 without slicing, but does return a new list.
Some other remarks:
If you omit the start value, it defaults to 0, and the end value, if omitted, defaults to the length of the list. Thus, list2[0:len(list2)] can be written as list2[:].
negative values count from the end. list2[:len(list2)-1] can be written as list2[:-1].
Because the upper bound is not inclusive. That means if your list has 1 element, you need to put 1, not 0, to include it in the slice. list[0:0] is effectively an empty slice, and if the upper bound was inclusive, there would be no way to get an empty slice. To get a slice with the first element only, you'll need list[0:1] instead.
(I'm using a list with just 1 element because it's super simple to understand. It obviously holds for lists with more items.)