【问题标题】:When text is same as the dict key, replace text to the dict value. However, don't replace text when text is same as the value in a list当 text 与 dict 键相同时,将 text 替换为 dict 值。但是,当文本与列表中的值相同时,不要替换文本
【发布时间】:2021-10-25 10:47:19
【问题描述】:

如何用 dict 替换文本,但不替换 skip_words 列表中的文本?

my_text = "HelloWorld foobar Hello bar..."

my_dict = {
    "Hello": "Hi",
    "bar": "rab",
    ...
}

skip_words = ["HelloWorld", "foobar"]

for a, b in my_dict.items():
    my_text = my_text.replace(a, b)

我想替换 Hello -> Hibar -> rab,但我不想替换 HelloWorldfoobar,因为它们在 skip_words 列表中。

【问题讨论】:

  • 我正在评论您的其他帖子,但您删除了它...这取决于字符串的长度以及您是否希望代码通用。想象一下,您有一个包含 100 万个字符的字符串,并且要执行 100 次替换。您将需要阅读约 1 亿个字符。此外,替换的顺序可能会影响输出。如果您的替换只是单词,更好的解决方案可能是拆分并检查每个单词。在不了解所有细节的情况下,我没有完美的答案。您可以在您的条件下对多个替换进行计时,看看这是否可以接受。

标签: python


【解决方案1】:

一种方法是使用替换函数进行简单的正则表达式替换;


import re

my_dict = { "Dog": "dog", "Cat": "cat" }
skip_words = set(["The Dog", "The Cat"])

result = re.sub(
    f'({"|".join(skip_words)}|{"|".join(my_dict.keys())})', 
    lambda x:x.group() if x.group() in skip_words else my_dict[x.group()], 
    "The Dog is Dog Dog Dog..."
)

print(result)

>>> The Dog is dog dog dog...

简短说明;

f'({"|".join(skip_words)}|{"|".join(my_dict.keys())})', 

创建一个正则表达式字符串进行匹配,由所有跳过的词(第一个)和所有的替换词组成。正则表达式将匹配其中任何一个。

lambda x:x.group() if x.group() in skip_words else my_dict[x.group()], 

一个函数,它为skip_words中的单词返回单词本身,或者为任何其他匹配的单词从my_dict中查找的版本返回。这意味着,跳过的单词不会被替换,其他匹配项会被替换。

请注意,我将跳过的单词放在一个集合中以便更轻松、更有效地查找。

【讨论】:

  • 非常感谢!!!
【解决方案2】:

您应该自己在文本中找到或创建一个模式。

例如,如果您想替换 "The" 之后的所有 "Dog"s,您可以这样做:

In [1]: import re
In [2]: re.sub(r"(?<!\bThe\W)\bDog", "dog", text)
Out[2]: 'The Dog is dog dog dog...'

这称为Negative Lookbehind

【讨论】:

    【解决方案3】:

    不要在循环中使用replace,这样效率非常低,因为每次替换都需要重新读取整个字符串。

    而是制作一个正则表达式并将每个匹配项传递给一个函数以将值映射到您的字典:

    import re
    regex = '|'.join('(?<!The )%s' % w for w in my_dict.keys())
    re.sub('(%s)' % regex, lambda x: my_dict[x.group()], my_text)
    

    输出:'The Dog is dog dog dog...'

    或者,或者,将文本拆分为单词并测试每个单词的匹配。请注意,这仅适用于完全独立的单词(请参阅最后一个“Dog”由于“...”而不会被替换):

    ' '.join(my_dict.get(w, w) for w in my_text.split())
    

    输出:'The dog is dog dog Dog...'

    【讨论】:

    • 谢谢,但是如何不替换在skip_words 中找到的文本?
    • The 在前面时是否总是例外?
    • 我认为是的..?其实文本中的字符都是中文的
    • @OAO 检查我的更新
    • 哦,对不起。它并不总是以The 开头。不过谢谢
    猜你喜欢
    • 2023-01-27
    • 2021-10-06
    • 1970-01-01
    • 2020-02-25
    • 2019-11-16
    • 1970-01-01
    • 2012-10-28
    • 2022-11-17
    • 1970-01-01
    相关资源
    最近更新 更多