我试图找到在Python快速的方法来检查,如果条件的列表可以对字符串从50到50000个字符大小不等的匹配。在Python中找到一个字符串是否匹配单词,短语和布尔逻辑与列表中的任何术语的最快方法是什么?
一个术语可以是:
- 一个字,例如。 “苹果”
- 的短语,如: “樱桃派”
- 单词和短语,例如布尔与操作。 “甜馅饼和咸味馅饼和酥皮”
一场比赛就是围绕字边界存在一个词或短语,所以:
match(term='apple', string='An apple a day.') # True
match(term='berry pie', string='A delicious berry pie.') # True
match(term='berry pie', string='A delicious blueberry pie.') # False
我公司目前拥有约40项,其中大部分都是简单的词。项的数量将随着时间而增加,但我不希望它获得超越400
我没有兴趣在短期(一个或多个)的字符串匹配,或在字符串中匹配,我只是需要一个真/假值对每个串的匹配 - 这是更可能是没有条件将匹配的字符串,因此对于1 500,其中它的比赛,我可以存储以便进一步处理的字符串。
速度是最重要的标准,我想利用那些比我聪明现有的代码,而不是试图实现一个白色的纸。 :)
到目前为止,最快的解决方案,我想出来的是:
(?i)(\b(apple|cherry pie)\b|((?=.*\bsweet pie\b)(?=.*\bsavoury pie\b)(?=.*\bmeringue\b))|((?=.*\bchicken pie\b)(?=.*\bbeef pie\b)))
因此,所有的条款一起进行或操作,忽略大小写:
def data():
return [
"The apple is the pomaceous fruit of the apple tree, species Malus domestica in the rose family (Rosaceae).",
"This resulted in early armies adopting the style of hunter-foraging.",
"Beef pie fillings are popular in Australia. Chicken pie fillings are too."
]
def boolean_and(terms):
return '(%s)' % (''.join(['(?=.*\\b%s\\b)' % (term) for term in terms]))
def run():
words_and_phrases = ['apple', 'cherry pie']
booleans = [boolean_and(terms) for terms in [['sweet pie', 'savoury pie', 'meringue'], ['chicken pie', 'beef pie']]]
regex = re.compile(r'(?i)(\b(%s)\b|%s)' % ('|'.join(words_and_phrases), '|'.join(booleans)))
matched_data = list()
for d in data():
if regex.search(d):
matched_data.append(d)
正则表达式作为卷起,单词/短语被包装在\ b中用于单词边界,布尔ANDs使用超前,以便所有术语都匹配,但不必按特定顺序匹配。
Timeit结果:
print timeit.Timer('run()', 'from __main__ import run').timeit(number=10000)
1.41534304619
没有向前看符号(即布尔与运算)。这实在是快,但一旦他们投入速度减慢显着。
是否有人对如何可以改善的想法?有没有一种方法来优化lookahead,或者可能是一种完全不同的方法?我不认为词干会起作用,因为它与匹配的词会有点贪婪。
其实,我不认为你的解决方案甚至是正确的。它不是匹配'甜馅饼和美味的馅饼和蛋白酥皮',它似乎匹配'甜馅饼那么美味的馅饼然后蛋白酥皮'(也就是说,短语不得不按照给定的顺序*匹配。 – Malvolio 2011-03-25 01:25:39
顺序无关紧要在我构建的正则表达式中 - 已经测试并确认它可以正常工作 – johanati 2011-03-25 01:35:20
请使用'timeit'并发布结果 – 2011-03-25 01:47:49