rreplace - Bir dizedeki ifadenin son tekrarlaması nasıl değiştirilir?


139

Python'da dizeleri değiştirmenin hızlı bir yolu var mı, ancak baştan başlamak yerine replacesonuna kadar mı? Örneğin:

>>> 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
İyi bir soru, böylesine basit bir sorunun karmaşık çözümlerine bakarak.
Justin Ardini

3
Aşağıdaki cevaplarda bu soruya eklenmesi 9 yıl (!) Süren zarif bir astar var, bulmak için aşağı kaydırın.
John D

Yanıtlar:


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
Çok hoş! Programımdaki tipik bir dizgideki (> 500 karakter) bir ifadenin son tekrarını değiştirmenin bilimsel olmayan bir karşılaştırmasında çözümünüz Alex'in çözümünden üç kat ve Mark'ın çözümünden dört kat daha hızlıydı. Yanıtlarınız için herkese teşekkürler!
Barthelemy

2
Teşekkürler, işe yarıyor. .replaceYöntem, birinci n oluşumları yerine anlatır üçüncü opsiyonel argüman 'sayısı' alır. Bu -1 gibi bir şey alırsa sezgisel olmaz mıydı ama maalesef olmayacak, bu yüzden çözümünüze ihtiyacımız var.
kakule

17

Bunu yapmanın en etkili yolu gibi davranmayacağım, ama basit bir yol. Söz konusu tüm dizeleri tersine çevirir str.replace, ters dizeleri kullanarak sıradan bir değiştirme gerçekleştirir , ardından sonucu doğru yönde geri döndürür:

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

İşte bir astar:

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

Tüm eski dize oluşumları yeni ile değiştirilen dizelerin s kopyasını döndürür . İlk maks . Yer değiştirme olayları değiştirilir.

ve kullanımda bunun tam bir örneği:

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

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

1
Güzel! Sonrasında virgül kaldırmak için kullanılır: line = "".join(line.rsplit(",", 1))daha sonra dolgu alanı tutarken.
torun

9

Dizeyi tersine çevirin, ilk oluşumu değiştirin ve tekrar ters çevirin:

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)

Çıktı:

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

'Eski' dizenin herhangi bir özel karakter içermediğini biliyorsanız, bunu normal ifadeyle yapabilirsiniz:

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

Sorun için özyinelemeli bir çözüm:

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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.