18

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.

Remi Guan
  • 21,506
  • 17
  • 64
  • 87
Vandexel
  • 609
  • 2
  • 7
  • 17

5 Answers5

21

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]
midori
  • 4,807
  • 5
  • 34
  • 62
  • 2
    Why do so much work, when you can just split on the *last* dot with either `str.rsplit()` or `str.rpartition()`? – Martijn Pieters Feb 26 '16 at 22:55
  • 1
    @minitoto: Your approach splits on *all* dots, requiring an additional `'.'.join()`. Using `.rsplit('.', 1)[0]`, or better still, `.rpartition('.')[0]` gives you the required result without having to join again. Both those methods also give you the tail, the part after the last dot. – Martijn Pieters Feb 27 '16 at 08:45
  • What is wrong in doing s[:-s.find('.')] to get everything before last '.' and doing s[s.rfind('.')+1:] to get everything after last dot? – OriginalCliche Mar 02 '16 at 10:58
15

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'
styvane
  • 59,869
  • 19
  • 150
  • 156
13

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]
GingerPlusPlus
  • 5,336
  • 1
  • 29
  • 52
4

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.

alexis
  • 48,685
  • 16
  • 101
  • 161
0

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'
DevShark
  • 8,558
  • 9
  • 32
  • 56
  • None of the other answers actually answer the part about isdigit. Mine is the only one providing the end to end answer. – DevShark Mar 02 '16 at 14:47