我有一个长为5*10^6的大字符串。在
我要做一些处理,把它分成16个字符的块。我使用了一个定制的函数来分割字符串,假设它的性能比拼接方法要好。在
其功能如下:def spliceSplitter(s):
sum = 0
while len(s) > 0:
block = s[:16]
# Assuming the process to be done with data block is calculating its length.
sum += len(block)
s = s[16:]
return sum
以及自定义函数:
^{pr2}$
我用了一个cProfiler对它们进行了测试,结果如下(以秒为单位的时间):String Length | Splice Splitter | Normal Splitter
---------------------------------------------------------
5000000 | 289.0 | 1.274
500000 | 0.592 | 0.134
50000 | 0.25 | 0.28
5000 | 0.001 | 0.003
我生成的字符串如下:s = ''.join([str(random.randint(1,9)) for x in xrange(5000000)])
我的问题:有没有一种Python式的方法可以获得与定制普通分配器相同或更好的效率?可能会先将整个字符串拆分,将其存储到一个列表中,然后进行迭代操作。在
为什么拼接分路器对于较小的串的性能更好?(只是好奇这个)
注意:我必须执行的process(data)没有返回值。在
编辑
使用成品率和改进的拼接分路器,性能结果如下:String Length | Splice Splitter | Normal Splitter | Yield/Generator
-------------------------------------------------------------------------------
5000000 | 0.148 | 1.274 | 0.223
500000 | 0.016 | 0.134 | 0.29
50000 | 0.003 | 0.28 | 0.005
5000 | ~0.000 | 0.003 | ~0.000
代码:def pythonicSplitter(s):
gen = (s[i:i+16] for i in xrange(0,len(s),16))
sum = 0
for data in gen:
sum += len(data)
return sum
def spliceSplitter(s):
sum = 0
for x in xrange(0, len(s), 16):
block = s[x:x+16]
# Assuming the process to be done with data block is calculating its length.
sum += len(block)
return sum
提高绩效的原因:拼接拆分器在每次迭代中使用Splice反复创建新字符串。s = s[16:]正如帕特里克·柯林在回答中指出的那样。这导致了~O(N^2)的时间复杂性。在
一旦字符串s的重复创建被s[x:x+16]取代,代码复杂度就降低到O(N*16),从而大大提高了它的性能。Yield/Generator函数执行相同的操作(pythonicSplitter()),但是由于对生成器(迭代器)的调用,完成操作所需的时间比拼接拆分器中使用的时间稍长。在
普通的拆分器也在做同样的事情,创建长度为16的块。但是,由于Python中的字符串是不可变的,因此创建这些块的时间复杂度明显大于内置的优化切片函数。在