在Python替换字符串时可以传递字典吗?
在PHP中,你可以使用 preg_replace($patterns, $replacements, $string)
这个函数,一次性替换多个内容,只需要传入一个包含模式和替换内容的数组。
那么在Python中,有什么类似的功能呢?
我注意到字符串和正则表达式的函数 replace()
和 sub()
并不支持字典作为输入……
根据rick的评论,我做了些修改以便更清楚:我的意思是有一个字典,字典的键是正则表达式模式,比如 '\d+S'
,而值则是希望能保持不变的字符串(最好没有反向引用)。现在我会根据这个来修改我的回答(也就是为了回答实际的问题)。
4 个回答
-2
这样做其实很简单:
replacements = dict(hello='goodbye', good='bad')
s = "hello, good morning";
for old, new in replacements.items():
s = s.replace(old, new)
你会发现很多地方,PHP的函数可以接收一组值(数组),而在Python中没有直接对应的功能。不过在Python中处理数组(列表)要简单得多,所以这个问题就没那么严重了。
-1
这里有一个简单的方法,可以使用reduce函数。
mynewstring=reduce(lambda a,(b,c): a.replace(b, c), mydict.items(), mystring)
10
最接近的可能是:
somere.sub(lambda m: replacements[m.group()], text)
比如说:
>>> za = re.compile('z\w')
>>> za.sub(lambda m: dict(za='BLU', zo='BLA')[m.group()], 'fa za zo bu')
'fa BLU BLA bu'
如果你想为在 replacements
中缺失的匹配项提供一个默认值,可以用 .get
来代替 []
索引。
编辑:rick真正想要的是有一个字典,字典的键是正则表达式模式,比如 '\d+S'
,而值则是常量字符串(希望没有反向引用)。这个食谱可以为这个目的进行调整:
def dict_sub(d, text):
""" Replace in 'text' non-overlapping occurences of REs whose patterns are keys
in dictionary 'd' by corresponding values (which must be constant strings: may
have named backreferences but not numeric ones). The keys must not contain
anonymous matching-groups.
Returns the new string."""
# Create a regular expression from the dictionary keys
regex = re.compile("|".join("(%s)" % k for k in d))
# Facilitate lookup from group number to value
lookup = dict((i+1, v) for i, v in enumerate(d.itervalues()))
# For each match, find which group matched and expand its value
return regex.sub(lambda mo: mo.expand(lookup[mo.lastindex]), text)
使用示例:
d={'\d+S': 'wot', '\d+T': 'zap'}
t='And 23S, and 45T, and 66T but always 029S!'
print dict_sub(d, t)
输出:
And wot, and zap, and zap but always wot!
你可以不构建 lookup
,直接使用 mo.expand(d.values()[mo.lastindex-1])
,但如果 d
非常大且匹配项很多,这样可能会稍微慢一点(抱歉,我没有精确测量/基准测试这两种方法,所以这只是个猜测;-)。