【发布时间】:2011-02-04 00:58:39
【问题描述】:
我正在寻找在一个非常大的字符串中替换大量子字符串的最快方法。这是我用过的两个例子。
findall() 感觉更简单、更优雅,但它花费的时间惊人。
finditer() 快速浏览一个大文件,但我不确定这是不是正确的做法。
这里有一些示例代码。请注意,我感兴趣的实际文本是大小约为 10MB 的单个字符串,这两种方法存在巨大差异。
import re
def findall_replace(text, reg, rep):
for match in reg.findall(text):
output = text.replace(match, rep)
return output
def finditer_replace(text, reg, rep):
cursor_pos = 0
output = ''
for match in reg.finditer(text):
output += "".join([text[cursor_pos:match.start(1)], rep])
cursor_pos = match.end(1)
output += "".join([text[cursor_pos:]])
return output
reg = re.compile(r'(dog)')
rep = 'cat'
text = 'dog cat dog cat dog cat'
finditer_replace(text, reg, rep)
findall_replace(text, reg, rep)
更新在测试中添加了 re.sub 方法:
def sub_replace(reg, rep, text):
output = re.sub(reg, rep, text)
return output
结果
re.sub() - 0:00:00.031000
finditer() - 0:00:00.109000
findall() - 0:01:17.260000
【问题讨论】:
-
第二个真的快很多吗?对我来说似乎很奇怪,他们应该大约需要。同时。而且我认为这两种方式都是正确的。
-
为什么不用re的sub方法?
-
对字符串使用 += 是 O(n^2) 操作,而构建列表并使用 "" 加入是 O(n)。
-
Sören:是的,这两种方法之间的区别是巨大的。
-
这是一个非常简化的例子吗?因为你可以使用
the_string.replace('dog', 'cat')。如果是,实际的正则表达式有多复杂?