rreplace – How to replace the last occurrence of an expression in a string?
Question:
Is there a quick way in Python to replace strings but, instead of starting from the beginning as replace
does, starting from the end? For example:
>>> def rreplace(old, new, occurrence)
>>> ... # Code to replace the last occurrences of old by new
>>> '<div><div>Hello</div></div>'.rreplace('</div>','</bad>',1)
>>> '<div><div>Hello</div></bad>'
Answers:
I’m not going to pretend that this is the most efficient way of doing it, but it’s a simple way. It reverses all the strings in question, performs an ordinary replacement using str.replace
on the reversed strings, then reverses the result back the right way round:
>>> def rreplace(s, old, new, count):
... return (s[::-1].replace(old[::-1], new[::-1], count))[::-1]
...
>>> rreplace('<div><div>Hello</div></div>', '</div>', '</bad>', 1)
'<div><div>Hello</div></bad>'
>>> def rreplace(s, old, new, occurrence):
... li = s.rsplit(old, occurrence)
... return new.join(li)
...
>>> s
'1232425'
>>> rreplace(s, '2', ' ', 2)
'123 4 5'
>>> rreplace(s, '2', ' ', 3)
'1 3 4 5'
>>> rreplace(s, '2', ' ', 4)
'1 3 4 5'
>>> rreplace(s, '2', ' ', 0)
'1232425'
Here is a recursive solution to the problem:
def rreplace(s, old, new, occurence = 1):
if occurence == 0:
return s
left, found, right = s.rpartition(old)
if found == "":
return right
else:
return rreplace(left, old, new, occurence - 1) + new + right
If you know that the ‘old’ string does not contain any special characters you can do it with a regex:
In [44]: s = '<div><div>Hello</div></div>'
In [45]: import re
In [46]: re.sub(r'(.*)</div>', r'1</bad>', s)
Out[46]: '<div><div>Hello</div></bad>'
Just reverse the string, replace first occurrence and reverse it again:
mystr = "Remove last occurrence of a BAD word. This is a last BAD word."
removal = "BAD"
reverse_removal = removal[::-1]
replacement = "GOOD"
reverse_replacement = replacement[::-1]
newstr = mystr[::-1].replace(reverse_removal, reverse_replacement, 1)[::-1]
print ("mystr:", mystr)
print ("newstr:", newstr)
Output:
mystr: Remove last occurence of a BAD word. This is a last BAD word.
newstr: Remove last occurence of a BAD word. This is a last GOOD word.
Here is a one-liner:
result = new.join(s.rsplit(old, maxreplace))
Return a copy of string s with all occurrences of substring old replaced by new. The first maxreplace occurrences are replaced.
and a full example of this in use:
s = 'mississipi'
old = 'iss'
new = 'XXX'
maxreplace = 1
result = new.join(s.rsplit(old, maxreplace))
>>> result
'missXXXipi'
Try this:
def replace_last(string, old, new):
old_idx = string.rfind(old)
return string[:old_idx] + new + string[old_idx+len(old):]
Similarly you can replace first occurrence by replacing string.rfind() with string.find().
I hope it helps.
Is there a quick way in Python to replace strings but, instead of starting from the beginning as replace
does, starting from the end? For example:
>>> def rreplace(old, new, occurrence)
>>> ... # Code to replace the last occurrences of old by new
>>> '<div><div>Hello</div></div>'.rreplace('</div>','</bad>',1)
>>> '<div><div>Hello</div></bad>'
I’m not going to pretend that this is the most efficient way of doing it, but it’s a simple way. It reverses all the strings in question, performs an ordinary replacement using str.replace
on the reversed strings, then reverses the result back the right way round:
>>> def rreplace(s, old, new, count):
... return (s[::-1].replace(old[::-1], new[::-1], count))[::-1]
...
>>> rreplace('<div><div>Hello</div></div>', '</div>', '</bad>', 1)
'<div><div>Hello</div></bad>'
>>> def rreplace(s, old, new, occurrence):
... li = s.rsplit(old, occurrence)
... return new.join(li)
...
>>> s
'1232425'
>>> rreplace(s, '2', ' ', 2)
'123 4 5'
>>> rreplace(s, '2', ' ', 3)
'1 3 4 5'
>>> rreplace(s, '2', ' ', 4)
'1 3 4 5'
>>> rreplace(s, '2', ' ', 0)
'1232425'
Here is a recursive solution to the problem:
def rreplace(s, old, new, occurence = 1):
if occurence == 0:
return s
left, found, right = s.rpartition(old)
if found == "":
return right
else:
return rreplace(left, old, new, occurence - 1) + new + right
If you know that the ‘old’ string does not contain any special characters you can do it with a regex:
In [44]: s = '<div><div>Hello</div></div>'
In [45]: import re
In [46]: re.sub(r'(.*)</div>', r'1</bad>', s)
Out[46]: '<div><div>Hello</div></bad>'
Just reverse the string, replace first occurrence and reverse it again:
mystr = "Remove last occurrence of a BAD word. This is a last BAD word."
removal = "BAD"
reverse_removal = removal[::-1]
replacement = "GOOD"
reverse_replacement = replacement[::-1]
newstr = mystr[::-1].replace(reverse_removal, reverse_replacement, 1)[::-1]
print ("mystr:", mystr)
print ("newstr:", newstr)
Output:
mystr: Remove last occurence of a BAD word. This is a last BAD word.
newstr: Remove last occurence of a BAD word. This is a last GOOD word.
Here is a one-liner:
result = new.join(s.rsplit(old, maxreplace))
Return a copy of string s with all occurrences of substring old replaced by new. The first maxreplace occurrences are replaced.
and a full example of this in use:
s = 'mississipi'
old = 'iss'
new = 'XXX'
maxreplace = 1
result = new.join(s.rsplit(old, maxreplace))
>>> result
'missXXXipi'
Try this:
def replace_last(string, old, new):
old_idx = string.rfind(old)
return string[:old_idx] + new + string[old_idx+len(old):]
Similarly you can replace first occurrence by replacing string.rfind() with string.find().
I hope it helps.