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 зі всіма входженнями старої підрядки, заміненої на нову . Перші максимальні місця зустрічаються.

і повний приклад цього у використанні:

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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.