我的代码执行以下操作:
n
个单词,右边返回n
个单词。在注意:在此上下文中,“word”是任何非空格字符的字符串。”“cow123美元”将是一个词,但“医疗保健”将是两个词。在
这是我的问题:
代码在300页上运行需要非常长的时间,而且随着n
的增加,时间往往会迅速增加。在
这是我的代码:
fileHandle = open('test_pdf.txt', mode='r')
document = fileHandle.read()
def search(searchText, doc, n):
#Searches for text, and retrieves n words either side of the text, which are returned separately
surround = r"\s*(\S*)\s*"
groups = re.search(r'{}{}{}'.format(surround*n, searchText, surround*n), doc).groups()
return groups[:n],groups[n:]
这是罪魁祸首:
^{pr2}$下面是如何测试此代码: 从上面的代码块复制函数定义并运行以下命令:
t = "The world is a small place, we $.205% try to take care of it."
print search("\$.205", t, 3)
我怀疑我遇到了灾难性的回溯,但我对regex太陌生了,无法指出问题所在。在
如何加速我的代码?
使用}在重新匹配对象上,或者使用
re.search
(如果只搜索固定字符串,甚至使用string.find
)来查找字符串,而不使用任何周围的捕获组。然后使用匹配的位置和长度(.start
和{find
的返回值加上搜索字符串的长度)。在匹配之前获取子字符串并对其执行/\s*(\S*)\s*\z/
等操作,在匹配之后获取子字符串并对其执行/\A\s*(\S*)\s*/
等操作。在另外,对于回溯的帮助:您可以使用类似
\s+\S+\s+
而不是\s*\S*\s*
(两块空白必须用非空白的非零数量分隔开,否则它们不会是两块),而且您不应该像您那样将两个连续的\s*
对接起来。我认为r'\S+'.join([[r'\s+']*(n))
将提供正确的模式来捕获n
前面的单词(但是我的Python已经生锈了,所以检查一下)。在您可以尝试使用
mmap
和适当的regex标志,例如(未测试):这只会降低内存使用率。。。在
另一种选择是有一个滑动窗口的单词(简单的例子,只有一个单词在前面和后面)…:
^{pr2}$我在这里看到了几个问题。第一个,也可能是最糟糕的,是“surround”regex中的所有内容都是可选的,不仅是可选的,而且是独立的可选的。给定此字符串:
…当
^{pr2}$searchText = "tritani"
和n = 1
时,它在找到第一个匹配项之前必须经过以下步骤:…然后它向前冲了一个位置,然后重新开始:
。。。等等。根据RegexBuddy的调试器,要达到偏移量大约需要150个步骤,才能使第一个匹配:
只需跳过一个单词,并使用
n=1
。如果您设置n=2
,则会得到以下结果:我相信你能看到事情的发展。请特别注意,当我将其更改为:
…它在20多步中找到第一个匹配。这是最常见的regex反模式之一:在应该使用
+
时使用*
。换句话说,如果它不是可选的,就不要把它当作可选的。在最后,您可能已经注意到
\s*\s*
自动生成的regex相关问题 更多 >
编程相关推荐