Right-to-left string replace in Python?
Question:
I want to do a string replace in Python, but only do the first instance going from right to left. In an ideal world I’d have:
myStr = "mississippi"
print myStr.rreplace("iss","XXX",1)
> missXXXippi
What’s the best way of doing this, given that rreplace
doesn’t exist?
Answers:
>>> myStr[::-1].replace("iss"[::-1], "XXX"[::-1], 1)[::-1]
'missXXXippi'
It’s kind of a dirty hack, but you could reverse the string and replace with also reversed strings.
"mississippi".reverse().replace('iss'.reverse(), 'XXX'.reverse(),1).reverse()
you may reverse a string like so:
myStr[::-1]
to replace just add the .replace
:
print myStr[::-1].replace("iss","XXX",1)
however now your string is backwards, so re-reverse it:
myStr[::-1].replace("iss","XXX",1)[::-1]
and you’re done.
If your replace strings are static just reverse them in file to reduce overhead.
If not, the same trick will work.
myStr[::-1].replace("iss"[::-1],"XXX"[::-1],1)[::-1]
>>> re.sub(r'(.*)iss',r'1XXX',myStr)
'missXXXippi'
The regex engine cosumes all the string and then starts backtracking untill iss
is found. Then it replaces the found string with the needed pattern.
Some speed tests
The solution with [::-1]
turns out to be faster.
The solution with re
was only faster for long strings (longer than 1 million symbols).
def rreplace(s, old, new):
try:
place = s.rindex(old)
return ''.join((s[:place],new,s[place+len(old):]))
except ValueError:
return s
rsplit
and join
could be used to simulate the effects of an rreplace
>>> 'XXX'.join('mississippi'.rsplit('iss', 1))
'missXXXippi'
You could also use str.rpartition()
which splits the string by the specified separator from right and returns a tuple:
myStr = "mississippi"
first, sep, last = myStr.rpartition('iss')
print(first + 'XXX' + last)
# missXXXippi
Using the package fishhook (available through pip), you can add this functionality.
from fishhook import hook
@hook(str)
def rreplace(self, old, new, count=-1):
return self[::-1].replace(old[::-1], new[::-1], count)[::-1]
print('abxycdxyef'.rreplace('xy', '--', count=1))
# 'abxycd--ef'
I want to do a string replace in Python, but only do the first instance going from right to left. In an ideal world I’d have:
myStr = "mississippi"
print myStr.rreplace("iss","XXX",1)
> missXXXippi
What’s the best way of doing this, given that rreplace
doesn’t exist?
>>> myStr[::-1].replace("iss"[::-1], "XXX"[::-1], 1)[::-1]
'missXXXippi'
It’s kind of a dirty hack, but you could reverse the string and replace with also reversed strings.
"mississippi".reverse().replace('iss'.reverse(), 'XXX'.reverse(),1).reverse()
you may reverse a string like so:
myStr[::-1]
to replace just add the .replace
:
print myStr[::-1].replace("iss","XXX",1)
however now your string is backwards, so re-reverse it:
myStr[::-1].replace("iss","XXX",1)[::-1]
and you’re done.
If your replace strings are static just reverse them in file to reduce overhead.
If not, the same trick will work.
myStr[::-1].replace("iss"[::-1],"XXX"[::-1],1)[::-1]
>>> re.sub(r'(.*)iss',r'1XXX',myStr)
'missXXXippi'
The regex engine cosumes all the string and then starts backtracking untill iss
is found. Then it replaces the found string with the needed pattern.
Some speed tests
The solution with [::-1]
turns out to be faster.
The solution with re
was only faster for long strings (longer than 1 million symbols).
def rreplace(s, old, new):
try:
place = s.rindex(old)
return ''.join((s[:place],new,s[place+len(old):]))
except ValueError:
return s
rsplit
and join
could be used to simulate the effects of an rreplace
>>> 'XXX'.join('mississippi'.rsplit('iss', 1))
'missXXXippi'
You could also use str.rpartition()
which splits the string by the specified separator from right and returns a tuple:
myStr = "mississippi"
first, sep, last = myStr.rpartition('iss')
print(first + 'XXX' + last)
# missXXXippi
Using the package fishhook (available through pip), you can add this functionality.
from fishhook import hook
@hook(str)
def rreplace(self, old, new, count=-1):
return self[::-1].replace(old[::-1], new[::-1], count)[::-1]
print('abxycdxyef'.rreplace('xy', '--', count=1))
# 'abxycd--ef'