如何在 Python 中优雅地迭代索引,用于字符串匹配文本中的子字符串列表?

How to iterate with index elegantly in Python, for string-matching a list of substrings inside text?

Text 是一个大字符串,patterns 是一个短(固定)字符串列表。 我的代码是:

def BruteForcePatternMatching(text, patterns):
    indices = []
    for pattern in patterns:
        for index in range(len(text) - 1):
            slide = text[index : index + len(pattern) - 1]
            if pattern == slide:
                indices.append(index)
    return indices

我的问题是是否有 'pythonic' 方法从文本中提取 'slide' 的迭代大小。

您正试图在您的文本中查找与列表 patterns 的匹配项。

如果 patterns 只是固定字符串,请使用 string.find()(但请注意,这只会找到第一个出现的地方 - 见下文)。

s = 'cat dog cow dog' # Note 'dog' occurs multiply
s.find('dog')
4
s.find('cow')
8
s.find('cat')
0

更一般地说,如果模式有正则表达式,或有重复的固定字符串,请使用 re.findall/iter()。请参阅此处的许多重复问题以获取示例。

import re
pat = re.compile(r'(cat|dog|cow)')
pat.findall("The cat and cow sat on the dog's catalog of doggerel")
# ['cat', 'cow', 'dog', 'cat', 'dog']

如果您还需要匹配发生的索引,请使用 re.finditer(),如@khachik 所示。

请注意,我们将所有模式合并到一个正则表达式中,然后使用一个 re.findall() 调用来搜索所有文本中每个模式的所有匹配项。 您当前的代码效率非常低:它试图通过 运行 在文本上滑动 window 来测试字符串相等性,并且具有嵌套循环:一个覆盖文本中的所有 N 索引和所有 P 模式;这将是 O(N*P) 阶,不可扩展。

假设您的模式不包含任何特殊的正则表达式字符或本身就是正则表达式:

import re
indices = [(m.start(), m.end()) for m in re.finditer("|".join(patterns), text)]