我正在寻找最快的方法来替换一个非常大的字符串中的大量子字符串。这里有两个我用过的例子。
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
结果
回复:sub()-0:00:00.031000
finditer()-0:00:00.109000
芬达尔()-0:01:17.260000
顺便说一下,使用findall_replace()的代码是不安全的,它可以返回未等待的结果:
显示
你可以,我认为你必须这样做,因为它确实是一个优化函数,使用
findall_replace()函数之所以很长,是因为在每次匹配时,都会创建一个新的字符串对象,您将通过执行以下代码看到:
注意,在这段代码中,我将
output = text.replace(match, rep)
替换为text = text.replace(match, rep)
,否则只替换最后一个出现的。finditer_replace()的长度与findall_replace()的长度相同:重复创建字符串对象。但是前者使用迭代器re.finditer(),而后者则在list对象之前构造,因此它更长。这就是迭代器和非迭代器的区别。
标准方法是使用内置的
顺便说一下,两个版本之间性能差异的原因是,第一个版本中的每个替换都会导致重新复制整个字符串。拷贝很快,但是当你一次拷贝10 MB时,足够的拷贝会变慢。
相关问题 更多 >
编程相关推荐