rreplace - Wie ersetze ich das letzte Vorkommen eines Ausdrucks in einer Zeichenfolge?

138

Gibt es in Python eine schnelle Möglichkeit, Zeichenfolgen zu ersetzen, aber anstatt wie am Anfang zu replacebeginnen, am Ende zu beginnen? Beispielsweise:

>>> 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>'
Barthelemy
quelle
5
Gute Frage, gemessen an den komplizierten Lösungen für ein so einfaches Problem.
Justin Ardini
3
In den Antworten unten finden Sie einen eleganten Einzeiler, der 9 Jahre (!) Dauerte, um zu dieser Frage hinzugefügt zu werden. Scrollen Sie einfach nach unten, um sie zu finden.
John D

Antworten:

195
>>> 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'
mg.
quelle
9
Sehr schön! In einem unwissenschaftlichen Benchmark zum Ersetzen des letzten Auftretens eines Ausdrucks in einer typischen Zeichenfolge in meinem Programm (> 500 Zeichen) war Ihre Lösung dreimal schneller als die von Alex und viermal schneller als die von Mark. Vielen Dank an alle für Ihre Antworten!
Barthelemy
2
Danke, es funktioniert. Die .replaceMethode verwendet ein drittes optionales Argument 'count', das sie anweist, die ersten n Vorkommen zu ersetzen. Wäre es nicht intuitiv gewesen, wenn das ein -1 wie wäre, aber leider nicht, also brauchen wir Ihre Lösung.
Kardamom
16

Ich werde nicht so tun, als wäre dies der effizienteste Weg, aber es ist ein einfacher Weg. Es kehrt alle fraglichen Zeichenfolgen um, führt einen normalen Austausch mit str.replaceden umgekehrten Zeichenfolgen durch und kehrt dann das Ergebnis richtig herum um:

>>> 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>'
Mark Byers
quelle
10

Hier ist ein Einzeiler:

result = new.join(s.rsplit(old, maxreplace))

Geben Sie eine Kopie der Zeichenfolge s zurück, wobei alle alten Teilzeichenfolgen durch neue ersetzt werden . Die ersten Maxreplace- Vorkommen werden ersetzt.

und ein vollständiges Beispiel dafür:

s = 'mississipi'
old = 'iss'
new = 'XXX'
maxreplace = 1

result = new.join(s.rsplit(old, maxreplace))
>>> result
'missXXXipi'
John D.
quelle
1
Nett! Wird verwendet, um nachgestellte Kommas aus Zeilen zu entfernen: line = "".join(line.rsplit(",", 1))und anschließend den Abstand zum Auffüllen beizubehalten.
Enkel
9

Kehren Sie einfach den String um, ersetzen Sie das erste Vorkommen und kehren Sie ihn erneut um:

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)

Ausgabe:

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.
Joe
quelle
5

Wenn Sie wissen, dass die 'alte' Zeichenfolge keine Sonderzeichen enthält, können Sie dies mit einem regulären Ausdruck tun:

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>'
Dave Kirby
quelle
1

Hier ist eine rekursive Lösung für das 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
naivnomore
quelle