rreplace - Como substituir a última ocorrência de uma expressão em uma string?


139

Existe uma maneira rápida no Python de substituir seqüências de caracteres, mas, em vez de começar do começo como no começo replace, do final? Por exemplo:

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

5
Boa pergunta, a julgar pelas soluções complicadas para um problema tão simples.
Justin Ardini 31/03/10

3
Há uma resposta elegante nas respostas abaixo, que levou 9 anos (!) Para ser adicionada a essa pergunta, basta rolar para baixo para encontrá-la.
John D

Respostas:


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

9
Muito agradável! Em uma referência não científica de substituição da última ocorrência de uma expressão em uma sequência típica no meu programa (> 500 caracteres), sua solução foi três vezes mais rápida que a solução de Alex e quatro vezes mais rápida que a solução de Mark. Obrigado a todos por suas respostas!
Barthelemy

2
Obrigado, funciona. O .replacemétodo usa um terceiro argumento opcional 'count', que informa para substituir as primeiras n ocorrências. Não seria intuitivo se isso levasse um -1, mas infelizmente não será, então precisamos da sua solução.
cardamomo

17

Não vou fingir que essa é a maneira mais eficiente de fazer isso, mas é uma maneira simples. Ele inverte todas as strings em questão, executa uma substituição comum usando str.replaceas strings invertidas e depois reverte o resultado da maneira correta:

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

10

Aqui está uma frase:

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

Retorne uma cópia da string s com todas as ocorrências de substring antigas substituídas por novas . As primeiras ocorrências de maxreplace são substituídas.

e um exemplo completo disso em uso:

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

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

1
Agradável! Utilizou-o para remover vírgulas finais das linhas: line = "".join(line.rsplit(",", 1))mantendo espaço de preenchimento posteriormente.
Neto

9

Apenas inverta a string, substitua a primeira ocorrência e inverta-a novamente:

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)

Resultado:

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.

5

Se você souber que a string 'antiga' não contém caracteres especiais, é possível fazer isso com uma 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>'

1

Aqui está uma solução recursiva para o problema:

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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.