替换所有特定词汇的出现次数

13

假设我有以下句子:

bean likes to sell his beans

我想替换文本中所有特定单词为另一个单词。例如,将bean替换为robert,将beans替换为cars

我不能仅使用str.replace,因为这样会将beans替换为roberts

>>> "bean likes to sell his beans".replace("bean","robert")
'robert likes to sell his roberts'
我只需要更改整个单词,而不是出现在其他单词中的单词。我认为可以通过使用正则表达式来实现这一点,但不知道如何做得正确。
4个回答

22
如果您使用正则表达式,可以使用\b指定单词边界:
import re

sentence = 'bean likes to sell his beans'

sentence = re.sub(r'\bbean\b', 'robert', sentence)
# 'robert likes to sell his beans'

这里不将“beans”更改为“roberts”,因为末尾的“s”不是单词边界:\b匹配空字符串,但仅限于单词开头或结尾。

第二个替换是为了完整性:

sentence = re.sub(r'\bbeans\b', 'cars', sentence)
# 'robert likes to sell his cars'

1
我想括号并不是必须的,只是让正则表达式更易读(至少对我来说是这样)。 - Alex Riley
1
由于某种原因,这似乎无法获取所有“U.S.”的出现。 - Kahless

4

如果你逐个替换单词,可能会多次替换同一个单词(而不是得到想要的结果)。为了避免这种情况,可以使用函数或lambda表达式:

d = {'bean':'robert', 'beans':'cars'}
str_in = 'bean likes to sell his beans'
str_out = re.sub(r'\b(\w+)\b', lambda m:d.get(m.group(1), m.group(1)), str_in)

这样一来,一旦将bean替换为robert,它就不会再被修改(即使robert也在您的输入单词列表中)。

georg所建议的那样,我使用dict.get(key, default_value)编辑了此答案。另一种解决方案(也是georg提出的):

str_out = re.sub(r'\b(%s)\b' % '|'.join(d.keys()), lambda m:d.get(m.group(1), m.group(1)), str_in)

我同意硬编码每个单词的1个正则表达式来替换应该会更快。但仍然存在一个问题,就是确保一旦被替换,一个单词不会再次被另一个正则表达式替换。 - nicolas
好的,我明白你的意思了。我只是假设OP指的是beanbeans作为例子。如果这是唯一需要修改的两个单词,那么是的,我同意,你的正则表达式会更快。 - nicolas
你可以这样简化lambda表达式:lambda m: d.get(m.group(1), m.group(1)) - georg
另一个可能的优化方法是从字典动态创建正则表达式: regex = r'\b(%s)\b' % '|'.join(d),这样就不必检查所有单词。 - georg
谢谢,我知道有更好的写法,但是想不起来 dict.get() :)。 - nicolas
显示剩余5条评论

0

这是一种不太优雅的方法,使用 folds

reduce(lambda x,y : re.sub('\\b('+y[0]+')\\b',y[1],x) ,[("bean","robert"),("beans","cars")],"bean likes to sell his beans")

-1
"bean likes to sell his beans".replace("beans", "cars").replace("bean", "robert")

将所有的“beans”替换为“cars”,并将“bean”替换为“robert”。这是因为.replace()返回原始字符串的修改实例。因此,您可以将其视为多个阶段。它基本上是这样工作的:

 >>> first_string = "bean likes to sell his beans"
 >>> second_string = first_string.replace("beans", "cars")
 >>> third_string = second_string.replace("bean", "robert")
 >>> print(first_string, second_string, third_string)

 ('bean likes to sell his beans', 'bean likes to sell his cars', 
  'robert likes to sell his cars')

在真实的任务中,我不能以这种方式进行操作,因为这些替换的顺序是不确定的。 - FrozenHeart

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