Why does extended slicing not reverse the list? - python

I'm slicing lists in python and can't explain some results.
Both of the following seem natural to me:
>>>[0,1,2,3,4,5][1:4:1]
[1, 2, 3]
>>>[0,1,2,3,4,5]
[::-1] == [5,4,3,2,1,0]
However,
>>>[0,1,2,3,4,5][1:4:-1]
[]
thought I expected it to be [3,2,1]. Why does it produce [ ]? Why does it not reverse the list? What happens first inside python, the step or the slicing?
I also found that
>>>[0,1,2,3,4,5][-3:-6:-1]
[3,2,1]

The third number in the slice is the step count. So, in [0,1,2,3,4,5][1:4:-1], the slicing starts at 1 and goes DOWN by 1 until it is less than 4, which is immediately is. Try doing this:
>>> [0,1,2,3,4,5][4:1:-1]
[4, 3, 2]

If you are slicing this then slicing will look like this [start:end:step]. For this one:
>>> [0,1,2,3,4,5][1:4:1]
[1, 2, 3]
It is staring from index 1 to index 3 because it exlcudes the index 4 with 1 step at a time.
You are getting an empty list in the second one because you are stepping -1 from 1st index. So this will be the solution.
>>> [0,1,2,3,4,5][4:1:-1]
[4, 3, 2]
This works because you are taking an index from 4 to one with -1 step forward.

Related

how the index works in Python

What does python do to find -2 items in the list? does iterate through the list?
a = [1, 2, 3, 4, 5]
print(a[-2])
I don't understand how it works.
Python programming language supports negative indexing of arrays, something which is not available in arrays in most other programming languages. This means that the index value of -1 gives the last element, and -2 gives the second last element of an array. The negative indexing starts from where the array ends.
(-) negative index iterates from last element to first element.
a = [1, 2, 3, 4, 5]
if you do a[-1] it returns last element (5).
if you do a[-2] it returns second last element(4) of the list and so on.

How to take x many items to the left of a particular index from a list, including 0 many items

Say I have a list
listt = [0,1,2,3,4,5,6,7]
And I want to take 3 items to the left of index 4, I could use this
listt[:4][-3:]
And get
[1, 2, 3]
The general formula is
listt[:index][-places:]
However, this does not work if I want 0 number of items left of 4
listt[:4][-0:]
Gives
[0, 1, 2, 3]
However, I want like to select 0 number of items, so it would be an empty list
[]
So now I am trying to find a general formula which takes 0 number of items into account.
Use listt[index-places:index].
This returns an empty list if 0 <= index < places or places <= 0.
Try this
listt = [0,1,2,3,4,5,6,7]
print(listt[:4][4-3:])
print(listt[:4][4-0:])
The general formula is
listt[:index][index-places:]
You are interpreting this wrongly,
print(listt[:4]) gives you the first 4 elements in the list
print(listt[-3:]) gives you the last 3 elements in the list
That's why when you printed listt[:4][-3:], you are actually printing the last 3 elements of [0, 1, 2, 3] which is [1, 2, 3]
Now, if you print (listt[-0:]), which still equals to printing (listt[:]) & therefore gives you the whole list. Printing listt[:4][-0:] will be like printing the whole list of listt[:4] which gives you back [0, 1, 2, 3]
Therefore, if you want to select none. It's either you select index 0 to 0 which is print(listt[0:0]) or select up to 0 which is print(listt[:0]). Otherwise, you gonna get some values.
Try
listt[k][k-n:k]
Negative index fails in case of zero, but this will do well. However, for n>k this won't work.

How to reorder a python list backwards starting with the 0th element?

I'm trying to go through a list in reverse order, starting with the -0 indexed item (which is also the 0th item), rather than the -1 indexed item, so that I'll now have the new list to use. I've come up with two ways to do this, but neither seems both concise and clear.
a_list = [1, 2, 3, 4, 5]
print(a_list[:1] + a_list[:0:-1]) # take two slices of the list and add them
# [1, 5, 4, 3, 2]
list_range = range(-len(a_list)+1,1)[::-1] # create an appropriate new index range mapping
print([a_list[i] for i in list_range]) # list comprehension on the new range mapping
# [1, 5, 4, 3, 2]
Is there a way in python 3 to use slicing or another method to achieve this more simply?
If you are up for a programming golf:
>>> a_list = [1, 2, 3, 4, 5]
>>> [a_list[-i] for i in range(len(a_list))]
[1, 5, 4, 3, 2]
I think your first suggestion is the cleanest way of doing this. If you're really optimizing for character count, you can remove two characters from the first slice:
print(a_list[:1] + a_list[:0:-1])
Shift everything left by one and reverse.
my_list.append(my_list.pop(0))
print my_list[::-1]

why n=[1,2,3,4,5,6,7,8],n[:6:-2] is [8] in Python?

n=[1,2,3,4,5,6,7,8]
n[:6:-2] #[8]
I think the result should be [6,4,2] not [8]
and what surprised me more is when I slice the list explicitly n[0:6,-2] then the output is []
I've checked documents, and noticed shallow copy,thus still no idea what happend under the hood
Ok let me explain :
Before your problem let's understand two concepts of slice:
First concept :
step in slice :
a[start:end:step] # start through not past end, by step
Second concept :
and you can also do slice of slice :
n=[1,2,3,4,5,6,7,8]
print(n[3:][2:])
output:
[6, 7, 8]
Now back to your problem let's solve it step by step:
first reverse the string:
n=[1,2,3,4,5,6,7,8]
print(n[::-1])
output:
[8, 7, 6, 5, 4, 3, 2, 1]
then give the step = 2:
n=[1,2,3,4,5,6,7,8]
print(n[::-1][0:len(n):2])
output:
[8, 6, 4, 2]
now slice from the result whatever you want:
n=[1,2,3,4,5,6,7,8]
print(n[::-1][0:len(n):2][1:])
output:
[6, 4, 2]
To achieve [6,4,2] you need to go backwards on the list, so first you want six, its position on the list its 5, first part is done, second you basically want to iterate backwards 2 positions until there is no more list
n = [1,2,3,4,5,6,7,8]
n[5:0:-2] // result [6,4,2]
Remember that your trying to go backwards, so first should be the position that you start, second the end position and last the number of steps (-2).
If you want to iterate backwards, starting from the 3rd element from right, that's the correct notation.
n=[1,2,3,4,5,6,7,8]
print n[len(n)-3::-2]
>[6, 4, 2]

Can someone explain this expression: a[len(a):] = [x] equivalent to list.append(x)

I'm at the very beginning of learning Python 3. Getting to know the language basics. There is a method to the list data type:
list.append(x)
and in the tutorial it is said to be equivalent to this expression:
a[len(a):] = [x]
Can someone please explain this expression? I can't grasp the len(a): part. It's a slice right? From the last item to the last? Can't make sense of it.
I'm aware this is very newbie, sorry. I'm determined to learn Python for Blender scripting and the Game Engine, and want to understand well all the constructs.
Think back to how slices work: a[beginning:end].
If you do not supply one of them, then you get all the list from beginning or all the way to end.
What that means is if I ask for a[2:], I will get the list from the index 2 all the way to the end of the list and len(a) is an index right after the last element of the array... so a[len(a):] is basically an empty array positioned right after the last element of the array.
Say you have a = [0,1,2], and you do a[3:] = [3,4,5], what you're telling Python is that right after [0,1,2 and right before ], there should be 3,4,5.
Thus a will become [0,1,2,3,4,5] and after that step a[3:] will indeed be equal to [3,4,5] just as you declared.
Edit: as chepner commented, any index greater than or equal to len(a) will work just as well. For instance, a = [0,1,2] and a[42:] = [3,4,5] will also result in a becoming [0,1,2,3,4,5].
One could generally state that l[len(l):] = [1] is similar to append, and that is what is stated in the docs, but, that is a special case that holds true only when the right hand side has a single element.
In the more general case it is safer to state that it is equivalent to extend for the following reasons:
Append takes an object and appends that to the end; with slice assignment you extend a list with the given iterable on the right hand side:
l[len(l):] = [1, 2, 3]
is equivalent to:
l.extend([1, 2, 3])
The same argument to append would cause [1, 2, 3] to be appended as an object at the end of l. In this scenario len(l) is simply used in order for the extending of the list to be performed at the end of l.
Some examples to illustrate their difference:
l = [1, 2]
l[len(l):] = [1, 2] # l becomes [1, 2, 1, 2]
l.extend([1, 2]) # l becomes [1, 2, 1, 2, 1, 2]
l.append([1, 2]) # l becomes [1, 2, 1, 2, 1, 2, [1, 2]]
As you note, l.append(<iterable>) doesn't actually append each value in the iterable, it appends the iterable itself.

Categories