2011-06-08 106 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”匹配。那么对于每场比赛我都会检查它是否存在于单词地图中。我猜会更有效率。