Python - 多个大文本插入

时间:2010-12-17 14:21:22

标签: python string templates

在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)。

赞赏的想法和建议。

谢谢。

布赖恩

4 个答案:

答案 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的内容放在第一个%sb中。

因此,假设您可以更改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()')