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 .
Related
This question already has answers here:
Understanding slicing
(38 answers)
Closed 6 years ago.
I'm trying to understand the logic behind reversing a slice using slice index and step.
First of all, I can reverse a string using the slice step like this:
a = "Hello"
a[::-1]
>>> 'olleH'
Also, I can reverse only a part of the string like this:
a = "Hello"
a[:2:-1]
>>> 'ol'
But when I try to reverse the string using another range like this:
a = "Hello"
a[1:3:-1]
>>> ''
I get an empty string.
However, if I inverse the ranges like this example:
a = "Hello"
a[4:1:-1]
>>> 'oll'
I get the reversed slice between indexes 1 and 4.
But, correct me if I'm wrong, I know that the first index from a slice must be less than the second index.
This is why when I run this example:
a = "Hello"
a[4:1]
>>> ''
I get an empty string.
So, can somebody explain to me why reversing a string (slice) while an inversed range with a negative step works, and using the logic of the first index being less than the second one in a slice will give an empty string.
Thanks for your answers.
It is not the case that the first number has to be less than the second, it just is the starting index, while the second is the ending index. Therefore, when you are going backwards (third index is -1), the starting index should be larger than the ending index, otherwise you'll get an empty string.
The syntax is
a[begin;end;step]
So when you use step -1 it will traverse through the string backwards and thus begin should be bigger than the end.
If you omit step it defaults to 1 and will traverse through the string forward and should begin must be smaller than the end.
Fun fact, you can also traverse in steps of -2
a = 'Hello, world!'
a[::-2] # => '!lo olH'
In looking at some python strings and functions, I discovered this strange quirk of python:
s = "hello"
print s[::-1]
which then prints: olleh
However, print s[len(s)-1:-1:-1] doesn't work. My understanding is that it should iterate from the last element s[len(s)-1] to the first element s[0]. However, it just prints an empty string '', which I believe is because in strings of some given length (say, 5), s[4] == s[-1]. But, I don't understand why python decides to use -1 instead of 4, which is the actual len(s).
Furthermore, s[len(s):0:-1] + s[0] works. Why is len(s) a valid index? Does python just convert len(s) to 0 arbitrarily?
P.S. This is in Python 2.7.8, I'm not sure if it also works in 3.x.x
EDIT: Confirmed to be the same in Python 3
The slice notation is this:
s[start:stop:step]
specifically, stop being up to but not including it. Translate this to what you're asking:
s[len(s)-1:-1:-1]
This is, based on the length of 5 for 'hello'
s[4:-1:-1]
or
s[4:4:-1]
which is an empty, or zero-length string.
I have given a much more in-depth exposition of the slice notation here: Explain Python's slice notation
Negative indexes are counted from the end of the sequence, so you're just getting [-1:-1:-1], or equivalently [4:4:-1] which is zero-length string.
Remember that indexes start at 0, not 1.
[len(s)-1] gets the last letter ('o')
:-1 is just 'o' again, because you're getting the last value.
So then you want to go from the last value... to the last value... reversed (-1). Of course that will return an empty string.
To answer your second question, that's because no errors are ever raised when using index notation. Try doing print s[32489375:2784:-123]
You are mapping backwards using a step of negative one. The default is:
from 0 to len(collection) by step
When you use a negative step the indices need to be reversed as well, or else you'll go the long way round. For example, from 0 to 5 by -1 goes: 0 + -1 = -1; -1 + -1 = -2 ... some time later an integer overflows ...)
In order to avoid this long walk around Python reverses the indices when step is negative and treats it as:
from len(collection) to 0 by step
This means that you need to deal with the start and end values in this case as negative integers from len(collection) - so, if you want to get the entire string in reverse, you are looking for:
s[-1:-(len(s) + 1):-1]
Or, in simpler terms:
from {the last item in the collection} to {the first item in the collection} by -1
This answer also has a good visual explanation for the indices.
This question already has answers here:
Understanding slicing
(38 answers)
Closed 8 years ago.
I am having a problem in understanding what happens when i put negative value to step in case of slicing.
I know [::-1] reverses a string. i want to know what value it assign to start and stop to get a reverse.
i thought it would be 0 to end to string. and tried
f="foobar"
f[0:5:-1]---> it gives me no output. why?
and i have read start should not pass stop. is that true in case of negative step value also?
can anyone help me to clear my doubt.
The reason why f[0:5:-1] does not generate any output is because you are starting at 0, and trying to count backwards to 5. This is impossible, so Python returns an empty string.
Instead, you want f[5:0:-1], which returns the string "raboo".
Notice that the string does not contain the f character. To do that, you'd want f[5::-1], which returns the string "raboof".
You also asked:
I have read start should not pass stop. is that true in case of negative step value also?
No, it's not true. Normally, the start value shouldn't pass the stop value, but only if the step is positive. If the step is negative, then the reverse is true. The start must, by necessity, be higher then the stop value.
You can think like that:
with f[0:5], 0 is the start position and 5-1 the end position.
with f[0:5:-1], 5 is the start position and 0+1 the end position.
In slicing the start position must be lower than the end position.
When this is not the case the result is an empty string. Thus f[0:5:-1] returns an empty string.
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.)