在文本中找到很多字符串 - Python

时间:2017-04-26 08:26:08

标签: python string

我正在寻找解决这个问题的最佳算法:拥有一个小句子的列表(或一个字典,一组),在更大的文本中找到所有出现的句子。列表中的句子(或词典或集合)约为600k,但平均形成3个单词。该文本平均长度为25个字。我刚刚格式化了文本(删除标点符号,全部小写并继续这样)。

这是我尝试过的(Python):

to_find_sentences = [
    'bla bla',
    'have a tea',
    'hy i m luca',
    'i love android',
    'i love ios',
    .....
]

text = 'i love android and i think i will have a tea with john'

def find_sentence(to_find_sentences, text):
    text = text.split()
    res = []
    w = len(text)
    for i in range(w):
        for j in range(i+1,w+1):
            tmp = ' '.join(descr[i:j])
            if tmp in to_find_sentences:
                res.add(tmp)
    return res


print find_sentence(to_find_sentence, text)

输出:

['i love android', 'have a tea']

在我的情况下,我使用了一套来加速in操作

1 个答案:

答案 0 :(得分:5)

快速解决方案是从句子中构建Trie并将此trie转换为正则表达式。对于您的示例,模式将如下所示:

(?:bla\ bla|h(?:ave\ a\ tea|y\ i\ m\ luca)|i\ love\ (?:android|ios))

这是example on debuggex

enter image description here

最好将'\b'添加为字边界,以避免匹配"have a team"

你需要一个小Trie script。它还不是官方软件包,但您可以在当前目录中将其here下载为trie.py

然后,您可以使用此代码生成trie / regex:

import re
from trie import Trie

to_find_sentences = [
    'bla bla',
    'have a tea',
    'hy i m luca',
    'i love android',
    'i love ios',
]

trie = Trie()
for sentence in to_find_sentences:
    trie.add(sentence)

print(trie.pattern())
# (?:bla\ bla|h(?:ave\ a\ tea|y\ i\ m\ luca)|i\ love\ (?:android|ios))

pattern = re.compile(r"\b" + trie.pattern() + r"\b", re.IGNORECASE)
text = 'i love android and i think i will have a tea with john'

print(re.findall(pattern, text))
# ['i love android', 'have a tea']

你花了一些时间来创建Trie和正则表达式,但处理速度应该非常快。

如果您想了解更多信息,请参阅related answer (Speed up millions of regex replacements in Python 3)

请注意,它找不到重叠的句子:

to_find_sentences = [
    'i love android',
    'android Marshmallow'
]
# ...
print(re.findall(pattern, "I love android Marshmallow"))
# ['I love android']

您必须使用正向前瞻修改正则表达式才能找到重叠的句子。