首页 > 解决方案 > 如何检查python中最长的子字符串

问题描述

我有一个文本和一个概念列表,如下所示。

concepts = ["data mining", "data", "data source"]
text = "levels and data mining of dna data source methylation"

我想确定concepts列表中的 是否在 中text并将所有出现的地方替换concepts[1:]concepts[0]。因此,上述文本的结果应该是;

"levels and data mining of dna data mining methylation"

我的代码如下所示:

concepts = ["data mining", "data", "data source"]
text = "levels and data mining of dna data source methylation"

if any(word in text for word in concepts):
    for terms in concepts[1:]:
        if terms in text:
            text=text.replace(terms,concepts[0])
        text=' '.join(text.split())
    print(text)

但是,我得到的输出是;

levels and data mining mining of dna data mining source methylation

看起来这个概念data被替换data mining为不正确的。更具体地说,我希望在替换时首先考虑最长的选项。

即使我更改concepts.

concepts = ["data mining", "data source", "data"]
text = "levels and data mining of dna data source methylation"

if any(word in text for word in concepts):
    for terms in concepts[1:]:
        if terms in text:
            text=text.replace(terms,concepts[0])
        text=' '.join(text.split())
    print(text)

我得到了上述代码的以下输出。

levels and data mining mining of dna data mining mining methylation

如果需要,我很乐意提供更多详细信息。

标签: python

解决方案


这里的问题是您的迭代策略,一次替换一个术语。因为您的替换术语包含您要替换的术语之一,所以您最终会替换您在之前的迭代中已经更改为替换术语的内容。

解决这个问题的一种方法是原子地进行所有这些替换,以便它们同时发生,并且输出永远不会影响其他替换的结果。有几个策略:

  1. 您可以将字符串分解为与您的各种术语匹配的标记,并在事后替换它们(并确保没有任何重叠)。
  2. 您可以使用对多个选项进行原子替换的函数。

#2 的一个例子是sub()Pythonre库的方法。这是它的使用示例:

import re

concepts = ["data mining", "data source", "data"]
text = "levels and data mining of dna data source methylation"

# Sort targets by descending length, so longer targets that
# might contain shorter ones are found first
targets = sorted(concepts[1:], key=lambda x: len(x), reverse=True)
# Use re.escape to generate version of the targets with special characters escaped
target_re = "|".join(re.escape(item) for item in targets)

result = re.sub(target_re, concepts[0], text)

请注意,这仍然会导致data mining mining您的原始替换集,因为它没有 .mining之后的现有概念data。如果您想避免这种情况,您可以简单地将要替换的实际项目也包含为替换目标,以便它在较短的期限之前得到匹配:

import re

concepts = ["data mining", "data source", "data"]
text = "levels and data mining of dna data source methylation"

# Sort targets by descending length, so longer targets that
# might contain shorter ones are found first
#
# !!!No [1:] !!!
#
targets = sorted(concepts, key=lambda x: len(x), reverse=True)
# Use re.escape to generate version of the targets with special characters escaped
target_re = "|".join(re.escape(item) for item in targets)

result = re.sub(target_re, concepts[0], text)

推荐阅读