215 votes

rreplace - Comment remplacer la dernière occurrence d'une expression dans une chaîne de caractères ?

Existe-t-il un moyen rapide en Python de remplacer des chaînes de caractères mais, au lieu de commencer par le début comme replace fait, en commençant par la fin ? Par exemple :

>>> 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>'

10 votes

Bonne question, à en juger par les solutions compliquées apportées à un problème aussi simple.

7 votes

Les réponses ci-dessous contiennent une phrase élégante qui a mis 9 ans ( !) à être ajoutée à cette question. Il suffit de faire défiler la page pour la trouver.

260voto

mg. Points 3729
>>> 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'

11 votes

Très bien ! Dans un benchmark non scientifique consistant à remplacer la dernière occurrence d'une expression dans une chaîne typique de mon programme (> 500 caractères), votre solution était trois fois plus rapide que celle d'Alex et quatre fois plus rapide que celle de Mark. Merci à tous pour vos réponses !

2 votes

Merci, ça marche. Le site .replace prend un troisième argument facultatif "count" qui lui indique de remplacer les n premières occurrences. N'aurait-il pas été intuitif que cette méthode prenne un -1 comme mais malheureusement ce n'est pas le cas, nous avons donc besoin de votre solution.

94voto

John D Points 2109

Voici un Une seule phrase :

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

Retourne une copie de la chaîne de caractères s avec toutes les occurrences de la sous-chaîne vieux remplacé par nouveau . Le premier maxreplace les occurrences sont remplacées.

et un exemple de cela en service :

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

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

25voto

Mark Byers Points 318575

Je ne vais pas prétendre que c'est la manière la plus efficace de procéder, mais c'est une manière simple. Elle inverse toutes les chaînes de caractères en question, effectue un remplacement ordinaire en utilisant la commande str.replace sur les chaînes inversées, puis renverse le résultat dans le bon sens :

>>> 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>'

17voto

Joe Points 1740

Il suffit d'inverser la chaîne, de remplacer la première occurrence et de l'inverser à nouveau :

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)

Sortie :

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.

5voto

Dave Kirby Points 12310

Si vous savez que l'"ancienne" chaîne de caractères ne contient pas de caractères spéciaux, vous pouvez le faire avec une 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>'

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X