rreplace - Как заменить последнее вхождение выражения в строке?

139

Есть ли в Python быстрый способ заменить строки, но вместо того, чтобы начинать с начала, как replaceделает, начиная с конца? Например:

>>> 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
Хороший вопрос, судя по сложным решениям такой простой задачи.
Джастин Ардини
3
В ответах ниже есть изящная однострочная строка, для добавления которой к этому вопросу потребовалось 9 лет (!), Просто прокрутите вниз, чтобы найти его.
Джон Д

Ответы:

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
Очень хорошо! В ненаучном тесте замены последнего вхождения выражения в типичной строке в моей программе (> 500 символов) ваше решение было в три раза быстрее, чем решение Алекса, и в четыре раза быстрее, чем решение Марка. Спасибо всем за ваши ответы!
Бартелеми
2
Спасибо, это работает. .replaceМетод принимает третий необязательный аргумент «Count» , который говорит, чтобы заменить первые п вхождения. Не было бы интуитивно понятно, если бы это приняло -1, но, к сожалению, это не так, поэтому нам нужно ваше решение.
кардамон
17

Я не собираюсь делать вид, что это самый эффективный способ сделать это, но это простой способ. Он переворачивает все рассматриваемые строки, выполняет обычную замену с использованием str.replaceперевернутых строк, а затем возвращает результат обратно в правильном направлении:

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

Вот одна строка:

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

Вернуть копию строки s, в которой все вхождения подстроки old заменены на new . Первые maxreplace вхождения заменяются.

и полный пример этого в использовании:

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

result = new.join(s.rsplit(old, maxreplace))
>>> result
'missXXXipi'
Джон Д
источник
1
Ницца! Использовал его для удаления запятых в строках: line = "".join(line.rsplit(",", 1))оставляя после себя отступы.
внук
9

Просто переверните строку, замените первое вхождение и снова переверните его:

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)

Вывод:

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

Если вы знаете, что «старая» строка не содержит специальных символов, вы можете сделать это с помощью регулярного выражения:

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

Вот рекурсивное решение проблемы:

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
источник