我試圖找到在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