Python,优化字符串连接的列表理解

时间:2015-05-20 06:54:39

标签: python numpy optimization list-comprehension

我正在使用cProfile在通过列表理解处理字符串的脚本上运行基准测试。我想优化的目标线看起来像这样:

signals = [('prefix' + str(day) + '_' + s) for s in signals]

其中day是整数。

此特定行使用了整个运行时间的33%。当然,在执行过程中它被称为百万次。

我尝试过几个明显的替代方案,包括''.join('prefix', str(day), '_', s)'prefix{:}_'.format(day),并使用numpy.core.defchararray.add将通过numpy.tile创建的前缀数组与signals连接起来。它们的速度比列表理解慢2倍。

此线路的速度优化是否还有空间?

3 个答案:

答案 0 :(得分:5)

这至少应该带来最小的改善:

# First precalculate the static part of the string
template = 'prefix%s_' % day + '%s'

# Then, use the %s string interpolation instead of joining strings with '+'  
# -->> Note: this proved to be wrong later... 
signals = [template % s for s in signals]

# Alternatively you could use map to compare efficiency (be aware of differences between python 2 and 3)
signals = map(template.__mod__, signals)

str.format%s插值更贵,所以我不会尝试。

现在让我们比较一下时间。你的方法:

>>> import timeit
>>> day = 45
>>> signals = ['aaaa', 'bbbb', 'cccccc', 'dddddddddddd']
>>> timeit.timeit("[('prefix' + str(day) + '_' + s) for s in signals]", 'from __main__ import day, signals')
1.35095184709592

我的第一个方法

>>> template = 'prefix%s_' % day + '%s'
>>> timeit.timeit("[template % s for s in signals]", 'from __main__ import template, signals')
0.7075940089748229

我的第二种方法

>>> timeit.timeit("map(template.__mod__, signals)", 'from __main__ import template, signals')
0.9939713030159822

因此,具有列表理解的模板的预先计算似乎获胜。还有一些事情需要考虑,例如,如果发电机对你来说足够好。

从有意义的评论中指出的信息

编辑,我添加了另一个解决方案:在紧密循环内部我们只将两个字符串连接在一起,所以我们可以直接连接它们而不是%-formatting < / p>

>>> template = 'prefix%s_' % day
>>> timeit.timeit("[template + s for s in signals]", 'from __main__ import template, signals')
0.39771016975851126

目前哪个是胜利者。

答案 1 :(得分:1)

尝试过:

signals = ['prefix{0}_{1}'.format(day, s) for s in signals]

作为基线,如果你只使用元组而不是字符串会怎么样?:

signals = [(day, s) for s in signals] 

答案 2 :(得分:1)

这可以更快

import numpy as np
signal = [x for x in range(9000)]
length = len(signal) 
prefArray = np.array(['prefix']*length )
dArray = np.array([str(day)]*length )
cArray = np.array(['_']*length )
sArray = np.array(["%s"%x for x in signal])

firstArray = np.core.defchararray.add(prefArray, dArray)
secondArray = np.core.defchararray.add(cArray, sArray)
result = np.core.defchararray.add(firstArray,secondArray)
print result