【问题标题】:Dictionary match issue with single pass multiple replacement单遍多次替换的字典匹配问题
【发布时间】:2017-04-19 09:35:26
【问题描述】:

您好,我正在尝试使用该函数一次性替换多个单词:

def multiple_replace(text, dict):
    regex = re.compile("(%s)" % "|".join(map(re.escape, dict.keys())))
    return regex.sub(lambda mo: dict[mo.string[mo.start():mo.end()]], text)

但我的问题是,如果我有一本字典:

dict = { 'hello1': 'hi', 'hello111' : 'GoodMorning', 'world' : 'earth' }

我试试

s = " hello111 world"
multiple_replace(s, dict)

函数匹配 hello1 而不是 hello111 符合预期 如果你们有任何线索,那就太好了!

我想反转搜索以确保函数从最长的键开始,因为我的键已排序,但这可能不是最好的方法。

【问题讨论】:

  • 使用单词边界 - regex = re.compile(r"\b(%s)\b" % "|".join(map(re.escape, dict.keys())))。或者按长度按降序对键进行排序,并使用非单词边界方法。
  • 尝试使用regex = re.compile("(%s)" % "|".join(sorted(dict, key=lambda k: len(k), reverse=True))) - 可以这样工作吗?

标签: python regex string replace regular-language


【解决方案1】:

Wiktor Stribiżew的评论权

先排序键给出单词边界。

def multiple_replace_sort(text, a_dict):
    regex = re.compile("(%s)" % "|".join(map(re.escape, sorted(a_dict, key=lambda obj: len(obj), reverse=True))))
    return regex.sub(lambda mo: a_dict[mo.string[mo.start():mo.end()]], text)


def multiple_replace_boundary(text, a_dict):
    regex = re.compile(r"(%s)\b" % "|".join(map(re.escape, a_dict.keys())))
    return regex.sub(lambda mo: a_dict[mo.string[mo.start():mo.end()]], text)

非单词项可能不适合上述方法,必须先分开,或者可能有更好的代码来处理它。

def multiple_replace_separate(text, a_dict):
    word, non_word = list(), list()
    for key in a_dict:
        word.append(key) if len(re.match(r'([a-zA-Z0-9]*)', key).group(0)) == len(key) else non_word.append(key)
    regex = re.compile(r"(%s)\B|(%s)\b" % ("|".join(non_word), "|".join(map(re.escape, word))))
    return regex.sub(lambda mo: a_dict[mo.string[mo.start():mo.end()]], text)

【讨论】:

  • 你不需要使用匹配对象的.start().end()来获取匹配值。只需使用.group() 获取值。此外,您的正则表达式仅使用尾随单词边界,这将不起作用。如果键以非单词字符开头/结尾,单词边界方法将不起作用。
  • 好吧,我只是按照原代码,做最少的改动。在组尾使用单个单词边界\b 用于转换最可能的单词。它有效。
  • 然后添加world- 键再试一次。
  • 我明白了,然后必须先将单词和非单词分开,然后再次出现排序问题。最好只对键进行排序 =]
猜你喜欢
  • 1970-01-01
  • 2020-08-27
  • 1970-01-01
  • 2019-09-06
  • 2018-01-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-08-17
相关资源
最近更新 更多