在Python中,将两大组文本A和B插入另一大组文本C中的最快方法(即单遍方法)是什么。
例如C:
.... ....
<<<A goes here>>>
.... ....
<<<B goes here>>>
.... ....
和“....”表示相当多的文本(即最多20k)。
在适当的占位符处插入A和B的最佳方法是什么,其中A和B也不是“小”量的文本(即最多2k)。
我的第一个想法是:
C.replace("<<<A goes here>>>", A)
C.replace("<<<B goes here>>>", B)
然而,由于它已经过了两次,我希望有一个单程解决方案。我考虑过一个正则表达式,但这似乎有点矫枉过正。 string.Template
是一个选项,但语法不合适(即$A
是一个占位符,可能与其他文本发生冲突,'$'不适合在别处转义。)
虽然A和B占位符在C中只出现一次,但我希望有一个可扩展到更多替换的解决方案 - 即与替换次数无关; O(n)其中n是len(C)。
赞赏的想法和建议。
谢谢。
布赖恩
答案 0 :(得分:3)
str.find的文档说它返回搜索到的字符串第一次出现的索引,对我来说这意味着它不会遍历整个字符串。如果你知道"<<<A goes here>>>"
总是先出现,我会这样做:
Aflag = "<<<A goes here>>>"
Bflag = "<<<B goes here>>>"
Aidx = C.find(Aflag)
Bidx = C.find(Bflag, Aidx+len(Aflag)+1)
newC = "".join((C[:Aidx], A, C[Aidx+len(Aflag)+1:Bidx], B, C[Bidx+len(Bflag)+1:]))
如果我的假设是正确的,这可以最大限度地减少对字符串的搜索。
答案 1 :(得分:2)
根据您使用的Python版本,您可以使用format
函数或%
运算符。 %
无处不在,所以这是一个例子:
'...\n%s\n...\n%s\n...' % (a, b)
这会将a
的内容放在第一个%s
和b
中。
因此,假设您可以更改C的占位符,请将它们转换为%s
,然后您就可以了。
答案 2 :(得分:1)
您可以应用任何字符串搜索算法,更具体地说是具有O(n)时间的KMP。既然你假设你将A和B分开,你可以在一次传递中完成。但是,它可能最终会成为O(n + k),因为你必须在找到它后替换它。
http://en.wikipedia.org/wiki/String_searching_algorithm
http://en.wikipedia.org/wiki/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm
在Python中我可能还有一种比较简单的方法,我不熟悉它,但是如果你从未见过这些算法,那么值得一看。
答案 3 :(得分:1)
最快的不是我想的那个! 替换是最快和最简单的
s = "\r\n"+("helllo"*100+"\r\n")*100
s2 = (s + "tag1" + s + "tag2" +s + "tag2" + s + "tag1" + s)*10
t1= ("t1"*100+"\r\n")*100
t2= ("t2"*100+"\r\n")*100
print "size = ",len(s2)
def f1():
return s2.replace("tag1",t1).replace("tag2",t2)
def f2():
return "\r\n".join([ x.replace("tag1",t1).replace("tag2",t2) for x in s2.split("\r\n")])
m = {"tag1":t1,"tag2":t2}
def f3():
p1 = 0
res= ""
while(p1 >= 0):
p2 = s2.find("tag",p1)
if (p2>=0):
res+= s2[p1:p2]+m[s2[p2:p2+4]]
p1 = p2+4
else :
res+= s2[p1:]
p1 = -1
return res
def g1():
for i in range(100):
f1()
def g2():
for i in range(100):
f2()
def g3():
for i in range(100):
f3()
if ( f1() != f2()):
print "problem"
if ( f1() != f3()):
print "problem"
import cProfile
cProfile.run('g1()')
cProfile.run('g2()')
cProfile.run('g3()')