rreplace - 如何替换字符串中最后一次出现的表达式?

207

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

9
好问题,从处理这样一个简单问题的复杂解决方案来看。 - Justin Ardini
7
下面的答案中有一个优雅的一行代码,花了9年(!) 才被添加到这个问题中,只需向下滚动即可找到它。 - Phil B
8个回答

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

11
非常好!在我的程序中,对一个典型字符串的最后一个表达式进行替换的非科学基准测试中(> 500个字符),您的解决方案比Alex的解决方案快三倍,比Mark的解决方案快四倍。感谢大家的回答! - Barthelemy
2
谢谢,它有效。.replace方法需要第三个可选参数“count”,告诉它替换前n个出现的内容。如果这个参数可以接受-1就更直观了,但不幸的是它不能,所以我们需要你的解决方案。 - cardamom

85

这里是一个单行代码

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'

2
不错!我用它来从行中删除尾随逗号:line = "".join(line.rsplit(",", 1)),同时保留后面的填充空格。 - grandchild
这里可以进行哪些修改以便在数据框列上使用它? - RSM

24

我不会假装这是最有效的方法,但它是一种简单的方法。它会颠倒所有的字符串,在颠倒的字符串上使用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>'

16

将字符串反转,替换第一次出现的内容,再次反转即可:

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.

当我使用这个时,数字书页的格式从未改变,而使用“join”函数则改变了格式。太好了! - info-farmer

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

1

试试这个:

def replace_last(string, old, new):
    old_idx = string.rfind(old)
    return string[:old_idx] + new + string[old_idx+len(old):]

同样,您可以通过将 string.rfind() 替换为 string.find() 来替换第一个出现的内容。
希望这能帮到您。

0
如果你有一个字符串列表,你可以使用列表推导式和字符串切片来覆盖整个列表。无需使用函数。
myList = [x[::-1].replace('<div>'[::-1],'<bad>'[::-1],1)[::-1] if x.endswith('<div>') else x for x in myList]

我使用if else来保留列表中不符合替换条件的项目,否则您的列表将只包含符合条件的项目。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接