在Python替换字符串时可以传递字典吗?

6 投票
4 回答
3768 浏览
提问于 2025-04-15 11:58

在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 非常大且匹配项很多,这样可能会稍微慢一点(抱歉,我没有精确测量/基准测试这两种方法,所以这只是个猜测;-)。

撰写回答