rreplace - จะแทนที่นิพจน์สุดท้ายในสตริงได้อย่างไร


144

มีวิธีที่รวดเร็วใน 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
คำถามที่ดีตัดสินโดยวิธีแก้ปัญหาที่ซับซ้อนสำหรับปัญหาง่ายๆเช่นนี้
Justin Ardini

3
คำตอบด้านล่างมีหนึ่งซับที่สวยงามซึ่งใช้เวลา 9 ปี (!) ในการเพิ่มคำถามนี้เพียงแค่เลื่อนลงเพื่อค้นหา
John D

คำตอบ:


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'

9
ดีมาก! ในเกณฑ์มาตรฐานที่ไม่เป็นไปตามหลักวิทยาศาสตร์ของการแทนที่นิพจน์สุดท้ายที่เกิดขึ้นในสตริงทั่วไปในโปรแกรมของฉัน (> 500 อักขระ) โซลูชันของคุณเร็วกว่าโซลูชันของ Alex สามเท่าและเร็วกว่าโซลูชันของ Mark ถึงสี่เท่า ขอบคุณทุกคนสำหรับคำตอบของคุณ!
Barthelemy

2
ขอบคุณมันได้ผล .replaceวิธีการใช้เวลาหนึ่งในสามตัวเลือกอาร์กิวเมนต์ 'นับ' ที่บอกว่ามันจะเข้ามาแทนที่เกิดขึ้น n แรก มันจะไม่ง่ายเลยถ้ามันจะเหมือน -1 แต่น่าเสียดายที่มันไม่ได้ดังนั้นเราจึงต้องการวิธีแก้ปัญหาของคุณ
กระวาน

18

ฉันจะไม่แสร้งทำเป็นว่านี่เป็นวิธีที่มีประสิทธิภาพมากที่สุด แต่เป็นวิธีง่ายๆ มันย้อนกลับสตริงทั้งหมดที่เป็นปัญหาทำการแทนที่ปกติโดยใช้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>'

17

นี่คือซับเดียว:

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

กลับสำเนาของสตริงsกับเหตุการณ์ที่เกิดขึ้นทั้งหมดของ substring เก่าแทนที่ด้วยใหม่ การเกิดmaxreplaceแรกจะถูกแทนที่

และตัวอย่างทั้งหมดของการใช้งานนี้:

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

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

1
ดี! ใช้เพื่อลบเครื่องหมายจุลภาคต่อท้ายออกจากเส้น: line = "".join(line.rsplit(",", 1))ในขณะที่รักษาช่องว่างในภายหลัง
หลาน

สิ่งที่สามารถแก้ไขได้ที่นี่เพื่อใช้ในคอลัมน์ dataframe?
RSM

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

2

นี่คือวิธีแก้ปัญหาแบบวนซ้ำสำหรับปัญหา:

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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.