2011-06-08 103 views
2

我想用python在字符串中查找某些關鍵字。該字符串是這樣的:蟒蛇正則表達式幾千字

A was changed from B to C 

所有我想找到的是「到C」部分,其中C是許多千言萬語之一。

此代碼會生成正則表達式的字符串:

pre_pad = 'to ' 
regex_string = None 
for i in words: 
    if regex_string == None: 
     regex_string = '\\b%s%s(?!-)(?!_)\\b' %(pre_pad, i) 
    else: 
     regex_string = regex_string + '|\\b%s%s(?!-)(?!_)\\b' %(pre_pad, i) 

,後來我做的:

matches = [] 
for match in re.finditer(r"%s" %regex_string, text): 
     matches.append([match, MATCH_TYPE]) 

此代碼在Linux上工作,但墜毀在MacOS與「夾縫OverflowError而渲染:定期表達代碼大小限制超出「

我意識到該regex_string很長,這是問題

print regex_string.__len__() 
63574 

的事業,我怎麼能解決這個問題所以這將總是工作,獨立的單詞的數量?

編輯:

我忘了提及的是,pre_pad有時是空的:pre_pad =「」,因此搜索pre_pad首先是不可能的。

除此之外,我首先構建整個regex_string然後將其與單詞匹配的原因是我必須爲數千個條目進行匹配。如果我不得不再次每次構建regex_string,這將導致非常差的性能。

哦,我需要知道哪個詞匹配。

+0

你甚至不應該用你的正則表達式來做這件事,你所描述的甚至不是像正則表達式那樣。只需將字符串拆分爲空格並遍歷單詞,以檢查所需關鍵字的「set」或「dict」。 – 2011-06-08 10:12:32

+0

不會這樣慢嗎? – memyself 2011-06-08 10:17:06

+2

爲什麼它會變慢? set和dict查找在設計上是非常快速的(並且必須是,實際上你在Python中做的每件事都以某種方式依賴於字典),並且我在大約1秒內將28MB字符串分割成400萬個元素的列表。你的琴絃多麼巨大?不成熟的優化只會浪費寶貴的開發人員時間,而且通常最終會給你提供次優代碼。 – 2011-06-08 10:28:04

回答

3

這不應該是你可以用一個巨大的正則表達式解決一個任務,並期待比這更好的性能:

pre_pad = 'to ' 
matches = [] 

for i in words: 
    regex_string = '\\b%s%s(?!-)(?!_)\\b' % (pre_pad, i) 
    for match in re.finditer(r"%s" % regex_string, text): 
     matches.append([match, MATCH_TYPE]) 

而且如果剖析你的代碼後,你看到鏈正則表達式的工作更快計算你正則表達式字符串長度,同時構建它並在2,3,10中分割完整任務以避免溢出。

P.S:

print len(regex_string) 

是更Python ...

+0

我忘了提到pre_pad有時是空的:pre_pad ='',所以先搜索pre_pad並不總是可能的。除此之外,之所以我先構建整個regex_string,然後再匹配,是因爲我必須爲數千個條目進行匹配。如果我不得不再次每次構建regex_string,這將導致非常差的性能。 – memyself 2011-06-08 10:05:08

+0

@memyself:無論如何,我無法得到'pre_pad'問題,我的建議是爲每個單詞製作一個正則表達式,或者分成大塊。然後相應地修復代碼。關於非常差的表演:**你是否確定了這個**?在百分比和時間上的性能損失是多少? – neurino 2011-06-08 10:17:45

+0

您的解決方案運行速度比我的解決方案慢1000倍。那是因爲單詞是幾千字。 – memyself 2011-06-08 10:35:41

0

所述的問題似乎很適合非正則表達式的解決方案。

或者,遍歷r'\b%s(\B+)(?!-)(?!_)\b' % pre_pad的匹配項,並檢查第一組匹配的單詞是否在您的字典中。

+0

你能舉個例子嗎? – Krab 2011-06-08 09:52:42

+0

@Krab:那麼,做一個線性掃描尋找'pre_pad'('to'),然後檢查它之前和之後的內容。 – NPE 2011-06-08 09:56:22

+0

這隻有在pre_pad不爲空時纔有效。但是我也有pre_pad爲空的情況。 – memyself 2011-06-08 10:14:53

0

我不是一個Python的專家,所以我的答案是不具有權威性。然而,在我看來,正則表達式在這種情況下並不是最好的工具。如果字符串

A was changed from B to C 

是固定的,那麼結構是不是足夠使用了,你要檢查的話in運營商迭代:

>>> "to blue" in "A was changed from red to blue" 
True 
1

您可以從解壓到C您通過簡單的正則表達式輸入,然後看看它在搜索優化的結構:

  • 一些樹
  • 有序列表用b inary搜索
  • 哈希結構(如Python的set

喜歡的東西

return match_from_regex in set_of_words 
+0

這基本上是更新的aix的解決方案。發佈我的答案時我錯過了更新。 – Krab 2011-06-08 10:03:39

+0

只適用於pre_pad不爲空。如果pre_pad爲空,那麼我仍然必須匹配每個單詞C. – memyself 2011-06-08 10:13:32

+0

問題是什麼?只需提取單詞,用pre_pad爲空的正則表達式進行檢查,然後查找它。 – Krab 2011-06-08 11:50:04

1

我會有點不同解決這個問題,說實話。我會製作一個文字地圖(我可以檢查該單詞是否存在O(1)複雜性)。然後搜索所有「to [\ w] +」正則表達式來獲取大文本中的每個「to」匹配。那麼對於每場比賽我都會檢查它是否存在於單詞地圖中。我猜會更有效率。