rreplace - Bagaimana cara mengganti kemunculan terakhir ekspresi dalam string?

144

Apakah ada cara cepat dalam Python untuk mengganti string tetapi, alih-alih memulai dari awal seperti replacehalnya, memulai dari akhir? Sebagai contoh:

>>> 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>'
Barthelemy
sumber
5
Pertanyaan bagus, dilihat dari solusi rumit untuk masalah sederhana seperti itu.
Justin Ardini
3
Ada satu kalimat yang elegan dalam jawaban di bawah yang membutuhkan waktu 9 tahun (!) Untuk ditambahkan ke pertanyaan ini, cukup gulir ke bawah untuk menemukannya.
John D

Jawaban:

200
>>> 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'
mg.
sumber
9
Sangat bagus! Dalam tolok ukur tidak ilmiah untuk mengganti kemunculan terakhir ekspresi dalam string tipikal dalam program saya (> 500 karakter), solusi Anda tiga kali lebih cepat daripada solusi Alex dan empat kali lebih cepat daripada solusi Mark. Terima kasih untuk semua atas jawaban Anda!
Barthelemy
2
Terima kasih, ini berhasil. The .replaceMetode mengambil sepertiga opsional argumen 'count' yang mengatakan itu untuk menggantikan n kejadian pertama. Bukankah akan intuitif jika itu akan mengambil -1 suka tetapi sayangnya tidak, jadi kami membutuhkan solusi Anda.
kapulaga
18

Saya tidak akan berpura-pura bahwa ini adalah cara paling efisien untuk melakukannya, tetapi ini cara yang sederhana. Ini membalikkan semua string yang dimaksud, melakukan penggantian biasa menggunakan str.replacestring terbalik, kemudian membalikkan hasilnya kembali ke arah yang benar:

>>> 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>'
Mark Byers
sumber
17

Ini satu baris:

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

Kembali salinan string s dengan semua kejadian dari substring lama diganti dengan yang baru . Kemunculan maxreplace pertama diganti.

dan contoh lengkap penggunaan ini:

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

result = new.join(s.rsplit(old, maxreplace))
>>> result
'missXXXipi'
John D
sumber
1
Bagus! Digunakan untuk menghapus tanda koma dari garis: line = "".join(line.rsplit(",", 1))sambil tetap mengisi spasi setelahnya.
cucu
apa yang bisa dimodifikasi di sini untuk digunakan pada kolom dataframe?
RSM
9

Balikkan saja string, ganti kemunculan pertama dan balikkan lagi:

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)

Keluaran:

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.
Joe
sumber
5

Jika Anda tahu bahwa string 'lama' tidak berisi karakter khusus, Anda dapat melakukannya dengan 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>'
Dave Kirby
sumber
2

Berikut ini solusi rekursif untuk masalah tersebut:

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.dll
sumber