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]
Related
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
I found this to be a bit strange. Can anyone explain to me: Why, if I have a list like this:
l = [1, 2, 3, 4, 5]
and I do this reassignment:
l[-1:0] = [99,]
then it inserts the 99 to the left of the 5, like so:
[1, 2, 3, 4, 99, 5]
We must assign to an iterable [99,], assigning to just the integer 99 will give an error, which might be a clue as to what's happening here... I guess?
According to the official Docs:
In the table s is an instance of a mutable sequence type, t is any iterable object and x is an arbitrary object that meets any type and value restrictions imposed by s
Note (1): t must have the same length as the slice it is replacing.
So, if you do l[-1] = 99, you are replacing the item in position -1 (that means, one less than the last) to the value 99.
On the other hand, if you do l[-1:0] = [99,], you taking the elements from index -1 to 0 (that means, a slice of length zero in the position -1), and replacing those by the elements of [99,] (that is why it must be an iterable), which effectively is a semantic insert.
When you slice a Python list with [start:end] you end up with another list. The beginning of the new list in your example is the location of the last element in your original list. Just because the value of l[-1:0] in your example is [] it does not mean that this is simply an empty list. Its value is an empty list, but the reference to l[-1:0] is to a sliced list within an existing list.
So in your example
l = [1,2,3,4,5]
# ^ l[-1:0] starts here but the size is 0
When you assign a list to a sliced position of another list, you are effectively performing list concatenation.
This is the equivalent of what you are doing.
l=[1,2,3,4,5]
l[4:0] = [99] # concatenate a new list at the position of the final element in the original list
# A different way to look at it
l[0:4] + [99] + l[4:]
The result again is effectively concatenating the two lists. More specifically, you are inserting the elements of a new list into the original at the position you've indicated. Using a literal integer such as 99 will result in an error because you cannot concatenate an int and a list directly. However, as others have pointed out, a slice assignment can use any iterable, so l[-1,0] = (99,) works by the same principle.
First, you'll need to know how the slicing works fully. You can have 3 values:
[start:end:step]
In your code, l[-1:0], using -1 as the start value will aim at the last value in the list, but it'll also try and find a list of values because of the end value being set. This is why you had to use a list to change the value.
To solve this issue, use l[-1] = 99 to change the last value of the list to 99 (assuming that's the intended result)
This question already has answers here:
How to find a missing number from a list?
(18 answers)
Closed 1 year ago.
I have a sorted list of integers:
l = [1,2,4,5]
I want to find the next free number in that range, in this case 3.
Are there available Python functions that can help with this? To create this manually I was thinking I would need to fetch the first and last index from l and create a new list, l_all, of all sequential integers inbetween those two values. Then walk and compare both lists and when a number exists in l_all but does not exist in l I would have my next free number. I'm curious if there is a more Pythonic way of doing this.
The suggested duplicate appears to be looking for a single missing value, but your case asks for the first available integer.
This can be done in a single line without a loop:
l = [1,2,4,5]
min(set(range(1, max(l)+1)) - set(l))
3
This is performing a set difference between a set of all possible integers from 1 to the max value in your list, set(range(1, max(l)+1)), and the set of values in your list, set(l). Sets are unsorted by nature, so you can use the min of the resulting set to find the first missing integer.
One advantage of using sets over lists to find the missing values is that it will still work without sorting your initial list, whereas any method involving looping across values will require the initial list to be sorted.
Also FYI, set(a) - set(b) could also be written as set(a).difference(set(b)). Both are functionally equivalent.
for i in range(len(l)):
a, b = i, i+1
if b < len(l):
if l[b] - l[a] > 1:
print(l[a] + 1)
This question already has answers here:
Python list multiplication: [[...]]*3 makes 3 lists which mirror each other when modified [duplicate]
(4 answers)
Closed 6 years ago.
Here:
a = [{}] * 2
a[0]['x'] = 1
print a
will show a is [{'x': 1}, {'x': 1}], likely python just copy the reference, a[1] is referring to a[0].
And
a = [0] * 2
a[0] = 1
print a
will show a is [1, 0], a[0] and a[1] is different.
Could somebody explain it? Thank you.
The difference comes from how the elements of your list are defined. In the first case, you create a list of two dictionaries, but those dictionaries contain the same reference, i.e., they're pointing to the same memory space. When you do a[0]['x'] = 1 You're changing the data the dictionary is pointing to and since both dictionaries in your list are pointing to the same space, they both appear to update.
In the second case, you have a list of two numbers, both of which technically point to the same spot (where python has pre-allocated zero). When you do a[0] = 1, you're not changing the data in the space where the first element is pointing, you're resetting where that element is pointing. Specifically you're redirecting it to 1. That way only the first element updates, but the second is still pointing at 0.
In the first example, the references in both positions of the list are pointing to the exact same dictionary. The correct way to do it is:
a = [{} for x in range(2)]
The second example is different:
a = [0] * 2
The number zero is copied across the list, but if you reassign the value on one of the positions that contain it, you'll simply copy a new number on the given index.
The key point is that in the first example the dictionary is a mutable object, whereas a number is not, and besides in the first example you performed an operation that mutated the dictionary, whereas in the second example you just reassigned the value in the list.
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.)