Right-to-left string replace in Python?

PythonString

Python Problem Overview


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?

Python Solutions


Solution 1 - Python

rsplit and join could be used to simulate the effects of an rreplace

>>> 'XXX'.join('mississippi'.rsplit('iss', 1))
'missXXXippi'

Solution 2 - Python

>>> myStr[::-1].replace("iss"[::-1], "XXX"[::-1], 1)[::-1]
'missXXXippi'

Solution 3 - Python

>>> 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).

Solution 4 - Python

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]

Solution 5 - Python

def rreplace(s, old, new):
    try:
        place = s.rindex(old)
        return ''.join((s[:place],new,s[place+len(old):]))
    except ValueError:
        return s

Solution 6 - Python

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

Solution 7 - Python

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'

Solution 8 - Python

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()

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionfredleyView Question on Stackoverflow
Solution 1 - PythonStephen EmslieView Answer on Stackoverflow
Solution 2 - PythoneumiroView Answer on Stackoverflow
Solution 3 - PythonovgolovinView Answer on Stackoverflow
Solution 4 - PythonSerdalisView Answer on Stackoverflow
Solution 5 - PythonAnaphoryView Answer on Stackoverflow
Solution 6 - PythonAustinView Answer on Stackoverflow
Solution 7 - PythonMichal PunčochářView Answer on Stackoverflow
Solution 8 - PythonsleeplessnerdView Answer on Stackoverflow