Slicing the second last character - python

I have this string here '[2,3,1,1,]'
Im new to slicing and I only know how to slice from the start and from the end but not somewhere between, not even sure if that is possible.
could someone tell me how I can slice this '[2,3,1,1,]' to this '[2,3,1,1]'
So removing the second last character only.

If you just want to delete the second last character, your can do like this,
s = "[2,3,1,1,]"
s[:-2] + s[-1]
# '[2,3,1,1]'
s[:-2] -> Will slice the string from 0 to -2 index location (without -2 index)
s[-1] -> Will fetch the last element
s[:-2] + s[-1] -> concatenation of the strigs

If you're sure you have that string, slice both characters and add the ] back on!
source_string = "[2,3,1,1,]"
if source_string.endswith(",]"):
source_string = source_string[:-2] + "]"
However, often lists stored as strings are not very useful - you may really want to convert the whole thing to a collection of numbers (perhaps manually removing the "[]" and splitting by ,, or using ast.literal_eval()), potentially converting it back to a string to display later
>>> source_string = "[2,3,1,1,]"
>>> import ast
>>> my_list = ast.literal_eval(source_string)
>>> my_list
[2, 3, 1, 1]
>>> str(my_list)
'[2, 3, 1, 1]'

You can use this for this one case
txt = "[2,3,1,1,]"
print(f"{txt[:-2]}{txt[-1]}")
Even tho storing lists as string is a bit weird
txt[:-2] will get the characters from 0 index to -2 index
txt[-1] will get the last character which is "]"
then I concatenate both with an f"" string
You can use this if you don't wanna use an f string
print(txt[:-2], txt[-1], sep="")
the "sep" argument is so there won't be space between the two prints

Using built-in functions such as str.rstrip
l = '[2,3,1,1,]'
l_new = f"{l.rstrip('],')}]" # it doesn't matter the order!
print(l_new)
or str.rpartition
a, _, b = l.rpartition(',')
l_new = a + b
print(l_new)
you can avoid an explicit slicing. See doc for details.
The 1st approach is universal, hence doesn't produce any side-effects. The 2nd may give rise to side-effects if the final last character is not a ,. If necessary use a check, i.e. str.endswith, to fix it.

Related

How to delete multiple substrings by their positions in Python?

I have a string, and I have a list of positions of the substrings that I need to delete:
text = 'ab cd ef gh'
positions = [[2, 5], [8, 11]]
Every element of the list contains start and end position of substring. End position is exclusive, and start position is inclusive. So the string should be transformed to:
text = 'ab ef'
Length of the list with positions is unknown, so the soultion can't be just hardcoded.
Is there any effective way to delete multiple substrings by their positions? Positions can't overlap.
Strings are immutable, so in-place deletion is a no-go. And successive concatenation is suboptimal.
You can convert the string to list so it can be mutated and simply wipe off the desired positions by deleting each unwanted slice. Use str.join to recreate your string:
text = 'ab cd ef gh'
lst = list(text)
for i in positions[::-1]: # iterate from behind so index does not shrink inwards
del lst[slice(*i)]
text = ''.join(lst)
print(text)
# 'ab ef'
Note that conversion to list for the mutation of immutable types is also suggested by the docs as best practice:
Concatenating immutable sequences always results in a new object. This
means that building up a sequence by repeated concatenation will have
a quadratic runtime cost in the total sequence length. To get a linear runtime cost, you must switch to one of the alternatives below:
if concatenating str objects, you can build a list and use
str.join() at the end or else write to an io.StringIO instance and
retrieve its value when complete
You have to offset for future indexes. So we first get the rest of the string (excluding the two indexes) via text[:2] + text[5:] and then we also need to offset it too, because we are removing items from the string. So, we'll add our offset to each position item.
text = 'ab cd ef gh'
positions = [[2,5],[8,11]]
offsetNextIndexes = 0
for position in positions:
text = text[:position[0] + offsetNextIndexes] + text[position[1] + offsetNextIndexes:]
offsetNextIndexes += position[0] - position[1]
print(text)
This should work easily.
" ".join(text.split()[0::2])
The slicing will help here to skip some parts, it works as
[start:end:difference]

Dot notation string manipulation

Is there a way to manipulate a string in Python using the following ways?
For any string that is stored in dot notation, for example:
s = "classes.students.grades"
Is there a way to change the string to the following:
"classes.students"
Basically, remove everything up to and including the last period. So "restaurants.spanish.food.salty" would become "restaurants.spanish.food".
Additionally, is there any way to identify what comes after the last period? The reason I want to do this is I want to use isDigit().
So, if it was classes.students.grades.0 could I grab the 0 somehow, so I could use an if statement with isdigit, and say if the part of the string after the last period (so 0 in this case) is a digit, remove it, otherwise, leave it.
you can use split and join together:
s = "classes.students.grades"
print '.'.join(s.split('.')[:-1])
You are splitting the string on . - it'll give you a list of strings, after that you are joining the list elements back to string separating them by .
[:-1] will pick all the elements from the list but the last one
To check what comes after the last .:
s.split('.')[-1]
Another way is to use rsplit. It works the same way as split but if you provide maxsplit parameter it'll split the string starting from the end:
rest, last = s.rsplit('.', 1)
'classes.students'
'grades'
You can also use re.sub to substitute the part after the last . with an empty string:
re.sub('\.[^.]+$', '', s)
And the last part of your question to wrap words in [] i would recommend to use format and list comprehension:
''.join("[{}]".format(e) for e in s.split('.'))
It'll give you the desired output:
[classes][students][grades]
The best way to do this is using the rsplit method and pass in the maxsplit argument.
>>> s = "classes.students.grades"
>>> before, after = s.rsplit('.', maxsplit=1) # rsplit('.', 1) in Python 2.x onwards
>>> before
'classes.students'
>>> after
'grades'
You can also use the rfind() method with normal slice operation.
To get everything before last .:
>>> s = "classes.students.grades"
>>> last_index = s.rfind('.')
>>> s[:last_index]
'classes.students'
Then everything after last .
>>> s[last_index + 1:]
'grades'
if '.' in s, s.rpartition('.') finds last dot in s,
and returns (before_last_dot, dot, after_last_dot):
s = "classes.students.grades"
s.rpartition('.')[0]
If your goal is to get rid of a final component that's just a single digit, start and end with re.sub():
s = re.sub(r"\.\d$", "", s)
This will do the job, and leave other strings alone. No need to mess with anything else.
If you do want to know about the general case (separate out the last component, no matter what it is), then use rsplit to split your string once:
>>> "hel.lo.there".rsplit(".", 1)
['hel.lo', 'there']
If there's no dot in the string you'll just get one element in your array, the entire string.
You can do it very simply with rsplit (str.rsplit([sep[, maxsplit]]) , which will return a list by breaking each element along the given separator.
You can also specify how many splits should be performed:
>>> s = "res.spa.f.sal.786423"
>>> s.rsplit('.',1)
['res.spa.f.sal', '786423']
So the final function that you describe is:
def dimimak_cool_function(s):
if '.' not in s: return s
start, end = s.rsplit('.', 1)
return start if end.isdigit() else s
>>> dimimak_cool_function("res.spa.f.sal.786423")
'res.spa.f.sal'
>>> dimimak_cool_function("res.spa.f.sal")
'res.spa.f.sal'

How to slicing a list element (get the substring of a list element)?

This program:
lijst = ('123-Abc','456-Def','789-Ghi')
print "lijst[1] = " + lijst[1]
print "lijst[1][4:] = " + lijst[1][4:]
print "lijst[1][4:1] = " + lijst[1][4:1]
has this output:
lijst[1] = 456-Def
lijst[1][4:] = Def
lijst[1][4:1] =
??
i had hoped that last line to be "D" !
So what is the correct syntax in order to get a substring from a list element?
(i'm running python 2.7.3 on a raspberry pi)
The correct syntax for slicing is [start:stop] and not [start:count] the way that it was used in the question. So you are actually looking for lijst[1][4:4+1] or lijst[1][4:5] for your last line.
There are all sorts of nice reasons for having this. You can use the same index to split a string into two parts, for example
lijst[1][:4] = "456-"
lijst[1][4:] = "Def"
and
lijst[1][:4] + lijst[1][4:] == lijst[1]
Note how you can leave out the first or last entry to indicate either the start or the end of the string.
Another nice feature of using indices like this is that the length of the string is given by stop-start. So
lijst[1][2:6] = "6-De"
and the length of this substring is 6 - 2 = 4
One last note is that you can also skip entries in the string by adding another step index:
lijst[1][0:7:2] = "46Df"
This goes from the start (index 0) to the end (index 7) and shows every second entry. Since you can leave out the start and the end indices, this is equivalent to
lijst[1][::2]
Getting a substring between the indices a and b (excluding b) is achieved using the slice [a:b]. And to get the character at index i you simply use [i] (think of the string as an array of characters).
>>> test = "456-Def"
>>> test[4:5]
'D'
>>> test[4:8]
'Def'
>>> test[4]
'D'

how to get the last part of a string before a certain character?

I am trying to print the last part of a string before a certain character.
I'm not quite sure whether to use the string .split() method or string slicing or maybe something else.
Here is some code that doesn't work but I think shows the logic:
x = 'http://test.com/lalala-134'
print x['-':0] # beginning at the end of the string, return everything before '-'
Note that the number at the end will vary in size so I can't set an exact count from the end of the string.
You are looking for str.rsplit(), with a limit:
print x.rsplit('-', 1)[0]
.rsplit() searches for the splitting string from the end of input string, and the second argument limits how many times it'll split to just once.
Another option is to use str.rpartition(), which will only ever split just once:
print x.rpartition('-')[0]
For splitting just once, str.rpartition() is the faster method as well; if you need to split more than once you can only use str.rsplit().
Demo:
>>> x = 'http://test.com/lalala-134'
>>> print x.rsplit('-', 1)[0]
http://test.com/lalala
>>> 'something-with-a-lot-of-dashes'.rsplit('-', 1)[0]
'something-with-a-lot-of'
and the same with str.rpartition()
>>> print x.rpartition('-')[0]
http://test.com/lalala
>>> 'something-with-a-lot-of-dashes'.rpartition('-')[0]
'something-with-a-lot-of'
Difference between split and partition is split returns the list without delimiter and will split where ever it gets delimiter in string i.e.
x = 'http://test.com/lalala-134-431'
a,b,c = x.split(-)
print(a)
"http://test.com/lalala"
print(b)
"134"
print(c)
"431"
and partition will divide the string with only first delimiter and will only return 3 values in list
x = 'http://test.com/lalala-134-431'
a,b,c = x.partition('-')
print(a)
"http://test.com/lalala"
print(b)
"-"
print(c)
"134-431"
so as you want last value you can use rpartition it works in same way but it will find delimiter from end of string
x = 'http://test.com/lalala-134-431'
a,b,c = x.rpartition('-')
print(a)
"http://test.com/lalala-134"
print(b)
"-"
print(c)
"431"

Get character based on index in Python

I am fairly new to python and was wondering how do you get a character in a string based on an index number?
Say I have the string "hello" and index number 3. How do I get it to return the character in that spot, it seems that there is some built in method that I just cant seem to find.
You just need to index the string, just like you do with a list.
>>> 'hello'[3]
l
Note that Python indices (like most other languages) are zero based, so the first element is index 0, the second is index 1, etc.
For example:
>>> 'hello'[0]
h
>>> 'hello'[1]
e
its just straight forward.
str[any subscript]. //e.g. str[0], str[0][0]
Check this page...
What you need is:
Strings can be subscripted (indexed); like in C, the first character of a string has subscript (index) 0.
There is no separate character type; a character is simply a string of size one.
Like in Icon, substrings can be specified with the slice notation: two indices separated by a colon.
Example:
>>> word[4]
'A'
>>> word[0:2]
'He'
>>> word[2:4]
'lp'
For your case try this:
>>> s = 'hello'
>>> s[3]
'l'

Categories