Python strings slicing - python

I have a variabel s="Siva"
and I have tried doing slicing using a logic
s[0:-5:-1]
According to the concept of slicing I am going in the backward direction, so it should ideally start from "S" and then go to "a","v","i" However when i tried running this I am getting an output as only "S" and even when I tried using s[0:-100:-1] it is still showing "S". Can anyone explain why this is happening?

The step count given by you in s[0:-5:-1] is -1, which means that string slicing will be reverse like 'a','v','i','S'.
But you are starting from s[0] which is "S" and due to the step count -1,it will print the previous character from the string "Siva",But there are no characters before 'S'.That's why it's stopping and only printing 'S'.
If you want the reverse of s = "Siva",
then simply write s[::-1].

Slicing is s[start:end:step] so if you want Savi you have to do
s[0] + s[-1:0:-1]
Start at -1 means start at the end of the string.
End at 0 means end at the beginning ignoring this first character.
Step -1 means go reverse one at a time.

Indeed, slicing accepts [start:stop:step] in its syntax. What you're saying with [0, -5, -1] is "start at index 0; advance until index -4 (inclusive); and do so with steps of -1".
Your string is of length 4 and so index -4 is actually index 0: s[-4] would be 'S'.
In other words, you're basically saying: "start at index 0 and finish at index 0 (inclusive)", which is why you get only 'S'. Anything smaller than -5, for instance: -10, would also give you 'S' only because there's nowhere further to go: it's essentially the same as what would happen if you tried to do s[0:100000:1]: you'd simply get 'Siva', because your string is 4<100000 characters long, and Python's behaviour in such cases is to just return all four (or, more generally: return as many characters as it can in "the direction of iteration", based on the sign of your step parameter, before reaching the end of the string).
On the other hand, if you try something that is greater than -5, such as, say, -2 or even just a positive 3, you'd get an empty string: that's because you'd basically be saying "start at index -4 and advance in the negative direction until you reach something greater" – this is never expected to happen and is somewhat "gibberishy" in nature, and I guess the way Python chose to deal with it is to just return an empty string in those cases.
This was intended to answer your question of "why this happens" while granting some intuition, hopefully; when it comes to a solution, if what you want is to simply grab the first letter and then reverse the rest: I'd simply use s[0] + s[-1:0:-1]. For fun I'll note that another option would be s[0] + s[1:][::-1].

Slicing is used with [start:stop:step]. If you use negative numbers for start it will start at the specified index, from the end.
If you want to print "Savi", I think you must have to slices :
s="Siva"
s[0] + s[-1::-1]

Perhaps what you expected couldn't be done with a string slice, but could still be done with indexing.
>>> ''.join(s[i] for i in range(0,-5,-1))
'SaviS'

Related

I got "TypeError: string indices must be integers" even though I'm using integers

I'm pretty early on in python (only learning for loop right now) and I have gotten into a bit of a problem.
As you can see I am using integers (as I have checked using type()) but is still raises the TypeError. Any idea why or how to fix it?
The problem is in line 8 where you are trying to break a string into multiple parts, but with a wrong syntax. You will have to perform slicing operation as
item = my_string[:6] # starting index is 0 by default, and final index is 6-1, i.e., 5
item = my_string[0:6] # starting index is 0, and final index is 6-1, i.e., 5
item = my_string[0:6:1] # starting index is 0, and final index is 6-1, i.e., 5, with a jump of 1 character to the right, i.e., index 0,1,2,3,4 and 5.
any of which will produce the same result, instead of
item = my_string[0,6]
as this will return TypeError which you can easily verify by just executing
"Hello"[0,6]
PS: You can achieve the same end result by doing
print(my_string.split(','))
as suggested by OneCricketeer. Also, if you want the user to input the string, try this
grocery_list = input("enter a comma separated string without spaces: ").split(',')
print(grocery_list)
Have fun coding!
This is just a syntax problem. If you want to get all characters up to index 6, you need to do
my_string[0:6]
In practice, you would usually use a shorter version (with the same functionality):
my_string[:6]
Additionally, in your code, you probably want to do
my_string[pos1:pos2]
Currently, you get pos1 and pos2 but don't use it.
Lastly, you could have searched "How to get the first 6 characters from a string in Python", and you might have found the answer yourself, e.g. here. Searching for your problem online and finding a solution is perhaps the most important skill you need now :)
Happy coding!
def make_list(my_string):
my_string += ' '
grocery_list = []
pos1 = 0
for item in range(my_string.count(",") + 1):
pos2 = my_string.find(",", pos1)
grocery_list += [my_string[pos1:pos2]]
pos1 = pos2+1
print(grocery_list)
call the function make_list('tomato,apple,orange')
This code work in my computer. I hope you get solution of your question.
The problem is that comma , to index the string. You have to use colon :
Correct syntax of slicing is (start:stop[:step])
item = mystring[0:6] # start at index 0, stop at index 6 (not included)
item = mystring[:6] # same notation, start at index 0

String slicing returning unexpected values

I hope this is a simple question! I am trying to reverse a number, and be given the digits in the 'even' positions. When I try to do this within one string slice, I am just given a single digit, even when I am expecing more. When I do it as two slices, I am given the correct answer, but I am unsure why.
For example, if I have the number 512341234, I would expect it to give me 3131, as I have first reversed the string (432143215) and then taken the even position numbers (4[3]2[1]4[3]2[1]5).
Below is the code which I have tried to use to make it work, but doing it as one slice only returns the single digit, whereas doing it as two means it returns the expected value. Why is this?
num = 512341234
str(num)[1::-2] #returns 1
str(num)[::-1][1::2] #returns 3131
Thanks!
Noah
1::-2 means to start at position 1 (the second character) and go backwards two characters at a time. You want to start somewhere near the end of the string, e.g.
num = 512341234
str(num)[-1::-2]
'42425'
num = 512341234
str(num)[-2::-2]
'3131'
But you’ll have to pick -1 or -2 based on which one of those characters is in an even position (i.e. based on the length of the string) to do this.

Cut zero chars (string[:-0]) from string - Python

Why does [:-0] return an empty string? There is a variable in my code which determines a length of string which have to be cut. The problem is that it returns empty string when there is int(0) in this variable.
Example:
def rightPass(word,value):
substring = word[:-value]
return substring
for i in range(3,-1,-1):
print rightPass('word',i)
>>> w
>>> wo
>>> wor
>>>
I do know that it is not a big deal to do this:
def rightPass(word,value):
substring = word[:-value] if value!=0 else word
return substring
But I can't find a reason why is [:-0] acting this way.
I though that it is because Python doesn't know -0 value but I tried it using 0 and the same problem occurred.
Can somebody explain it?
You are asking Python to create a new string from index 0 to index 0. And that's an empty slice.
The end value of a slice is exclusive. Python picks all characters from the starting index that come before the end index. Here -0 is the same thing as 0 (negative zero is the same thing as positive zero).
Note that that is different from using actual negative values; [0:-1] would take the length and replace the negative value with len(object) - 1 and use that as the end value, but this doesn't work for -0, because that is not a negative value!
You can use None instead of 0 if you wanted to slice to the end:
substring = word[:-value if value else None]
The second parameter in the slice is the end position.
[start : stop : step]
And the range of start to stop is half open, meaning it includes start up to but not including stop.
So [: 0] means start at [0] and stop at but don't include [0], which can only be empty string.

Why does s[len(s)-1:-1:-1] not work?

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.

find() function in python2.7.5

find('asdf','') finds an empty string in 'asdf' hence it returns 0.
Similarly, find('asdf','',3) starts to search for the string at index position 3 and hence return 3.
Since the last index is 3, find('asdf','',4) should return -1 but it returns 4 and starts to return -1 only if the starting index is more than or equal to (last_index)+2. Why is this so?
Because "asdf" without its first four characters still does contain "". A harder check comes into play when the index exceeds the length of the string, but having an index equal to the string is equivalent to "".find().
Here is how it works:
0 a 1 s 2 d 3 f 4
When you use 'asdf'.find(sub), it searches those five positions, labeled 0, 1, 2, 3, and 4. Those five. Those five. No more and no less. It returns the first one where 'asdf'[pos:pos+len(sub)] == sub. If you include the start argument to find, it starts at that position. That position. Not one less, not one more. If you give a start position greater than the greatest number in the list of positions, it returns -1.
In other words, the answer is what I already repeated in a comment, quoting another question answer:
The last position [for find] is after the last character of the string
Edit: it seems your fundamental misunderstanding relates to the notion of "positions" in a string. find is not returning positions which you are expected to access as individual units. Even if it returns 4, that doesn't mean the empty string is "at" position 4. find returns slice starts. You are supposed to slice the string starting at the given position.
So when you do 'asdf'.find('', 4), it starts at position 4. It finds the empty string there because 'asdf'[4:4+len('')]==''. It returns 4. That is how it works.
It is not intended that str.find has a one-to-one mapping between valid indexes into the actual string. Yes, you can do tons of other indexing like 'asdf'[100:300]. That is not relevant for find. What you know from find is that 'asdf'[pos:pos+len(sub)] == sub. You do not know that every possible index that would return '' will be returned by find, nor are you guaranteed that the number returned by find is a valid index into the string if you searched for an empty string.
If you have an actual question about some use of this functionality, then go ahead and ask that as a separate question. But you seem to already know how find works, so it's not clear what you're hoping to gain from this question.

Categories