>>> d = {'a':'b', 'c':'d'}
>>> s = "a c x"
>>> foo = s.split()
>>> ret = []
>>> for item in foo:
... ret.append(d.get(item,item)) # Try to get from dict, otherwise keep value
...
>>> " ".join(ret)
'b d x'
import re
# assuming global `d` and `s` as in the question
# a function that does the dict lookup with the global `d`.
def lookup(match):
return d[match.group()]
# Make the regex.
joined = '|'.join(re.escape(key) for key in d.keys())
pattern = re.compile(joined)
result = pattern.sub(lookup, s)
s = 'one two'
s = s.replace('one', 'two')
s = s.replace('two', 'three')
这将产生'three three',而不是'two three',因为来自第一替换的'two'本身将在第二步骤中被替换。然而,在它 * 应该 * 以这种方式工作的罕见情况下,这种方法是唯一实用的方法。 这种方法也不能很容易地固定以尊重单词边界,因为它必须匹配文本,并且“单词边界”可以用多种不同的方式来标记--通过不同种类的空格,但也可以在字符串的开头和结尾使用 without text。 最后,请记住,dict不是这种方法的理想数据结构,如果我们将遍历dict,那么它的键查找能力将是无用的;和in Python 3.5 and below, the order of dict s is not guaranteed(这使得顺序替换问题变得更糟)。相反,最好为替换指定一个元组列表:
d = [('Спорт', 'Досуг'), ('russianA', 'englishA')]
s = 'Спорт russianA'
for to_replace, replacement in d: # no more `.items()` call
s = s.replace(to_replace, replacement)
8条答案
按热度按时间ovfsdjhp1#
使用re:
这将只匹配整个单词。如果不需要,请使用以下模式:
注意,在这种情况下,如果某些字典条目是其他条目的子字符串,则应该按长度降序对单词进行排序。
cczfrluj2#
您可以使用reduce函数:
3df52oht3#
解决方案在这里找到(我喜欢它的简单):
vbkedwbf4#
单向,无环
d4so4syb5#
与ghostdog74几乎相同,尽管是独立创建的。一个不同之处是,使用d.get()代替d[]可以处理不在dict中的项。
htrmnn0y6#
如果key有空间,它会失败,这是一个类似ghostdog74和extaneons的压缩解决方案:
wqnecbli7#
我在类似的情况下使用了这个方法(我的字符串都是大写的):
希望这能在某种程度上有所帮助...:)
bkhjykvo8#
使用正则表达式
我们可以创建一个正则表达式来匹配查找字典中的任意键,方法是创建正则表达式来匹配每个键,并将它们与
|
组合在一起。我们使用re.sub
来进行替换,方法是给它一个函数来进行替换(当然,这个函数将进行字典查找)。这里,
re.escape
用于转义替换中任何具有特殊含义的字符(这样它们就不会干扰正则表达式的构建,并且可以按字面进行匹配)。此正则表达式模式将匹配出现在任何位置的子字符串,即使它们是单词的一部分或跨越多个单词。要避免此问题,请修改正则表达式,使其检查单词边界:
迭代使用
str.replace
只需遍历查找字典的
.items()
,并使用each调用.replace
,由于这个方法是returns a new string, and does not (cannot) modify the string in place,我们必须在循环中重新分配结果:这种方法编写简单,易于理解,但是它有许多警告。
首先,它的缺点是它按特定顺序连续工作。也就是说,每个替换都有可能干扰其他替换。请考虑:
这将产生
'three three'
,而不是'two three'
,因为来自第一替换的'two'
本身将在第二步骤中被替换。然而,在它 * 应该 * 以这种方式工作的罕见情况下,这种方法是唯一实用的方法。这种方法也不能很容易地固定以尊重单词边界,因为它必须匹配文本,并且“单词边界”可以用多种不同的方式来标记--通过不同种类的空格,但也可以在字符串的开头和结尾使用 without text。
最后,请记住,
dict
不是这种方法的理想数据结构,如果我们将遍历dict,那么它的键查找能力将是无用的;和in Python 3.5 and below, the order ofdict
s is not guaranteed(这使得顺序替换问题变得更糟)。相反,最好为替换指定一个元组列表:通过标记化
如果首先将字符串分割(tokenized),那么问题就会变得简单得多,这样一来,任何应该被替换的内容现在都是dict键的 exact match,这样就可以直接使用dict的查找,一次处理完整个字符串,同时也不用构建自定义正则表达式。
假设我们想要匹配完整的单词,我们可以使用一个更简单的、硬编码的正则表达式来匹配空格,它使用一个捕获组;通过将其传递给
re.split
,我们将字符串拆分为空白和非空白部分。现在我们在字典中查找每个标记:如果存在,就应该用对应的值替换,否则就不去管它(相当于用它自己替换它),字典
.get
方法很适合这个任务,最后,我们使用join the pieces back up,这样:更普遍的情况是,例如,如果要替换的字符串中可能有空格,则需要不同的标记化规则。然而,通常可以找到比第一节中的正则表达式更简单的标记化规则(通过暴力强制匹配所有键)。
特殊情况:替换单个字符
如果dict的键都是一个字符(从技术上讲,是Unicode码位),则可以使用更多特定的技术,详细信息请参见Best way to replace multiple characters in a string?。