Jib*_*Jib 10 python format join list
假设我有两个相同长度的列表:
a = ['a1', 'a2', 'a3']
b = ['b1', 'b2', 'b3']
Run Code Online (Sandbox Code Playgroud)
我想生成以下字符串:
c = 'a1=b1, a2=b2, a3=b3'
Run Code Online (Sandbox Code Playgroud)
实现这一目标的最佳方法是什么?
我有以下实现:
import timeit
a = [str(f) for f in range(500)]
b = [str(f) for f in range(500)]
def func1():
return ', '.join([aa+'='+bb for aa in a for bb in b if a.index(aa) == b.index(bb)])
def func2():
list = []
for i in range(len(a)):
list.append('%s=%s' % (a[i], b[i]))
return ', '.join(list)
t = timeit.Timer(setup='from __main__ import func1', stmt='func1()')
print 'func1 = ' + t.timeit(10)
t = timeit.Timer(setup='from __main__ import func2', stmt='func2()')
print 'func2 = ' + t.timeit(10)
Run Code Online (Sandbox Code Playgroud)
输出是:
func1 = 32.4704790115
func2 = 0.00529003143311
Run Code Online (Sandbox Code Playgroud)
你有一些权衡吗?
CB *_*ley 26
在我的系统上,这种实现比两个函数中的任何一个都要快,而且更紧凑.
c = ', '.join('%s=%s' % t for t in zip(a, b))
Run Code Online (Sandbox Code Playgroud)
感谢@JBernardo的建议改进.
在更新的语法中,str.format更合适:
c = ', '.join('{}={}'.format(*t) for t in zip(a, b))
Run Code Online (Sandbox Code Playgroud)
这产生了大致相同的输出,虽然它可以接受任何带有__str__方法的对象,因此两个整数列表仍然可以在这里工作.
eyq*_*uem 12
a = ['a1', 'a2', 'a3']
b = ['b1', 'b2', 'b3']
pat = '%s=%%s, %s=%%s, %s=%%s'
print pat % tuple(a) % tuple(b)
Run Code Online (Sandbox Code Playgroud)
给 a1=b1, a2=b2, a3=b3
.
然后:
from timeit import Timer
from itertools import izip
n = 300
a = [str(f) for f in range(n)]
b = [str(f) for f in range(n)]
def func1():
return ', '.join([aa+'='+bb for aa in a for bb in b if a.index(aa) == b.index(bb)])
def func2():
list = []
for i in range(len(a)):
list.append('%s=%s' % (a[i], b[i]))
return ', '.join(list)
def func3():
return ', '.join('%s=%s' % t for t in zip(a, b))
def func4():
return ', '.join('%s=%s' % t for t in izip(a, b))
def func5():
pat = n * '%s=%%s, '
return pat % tuple(a) % tuple(b)
d = dict(zip((1,2,3,4,5),('heavy','append','zip','izip','% formatting')))
for i in xrange(1,6):
t = Timer(setup='from __main__ import func%d'%i, stmt='func%d()'%i)
print 'func%d = %s %s' % (i,t.timeit(10),d[i])
Run Code Online (Sandbox Code Playgroud)
结果
func1 = 16.2272833558 heavy
func2 = 0.00410247671143 append
func3 = 0.00349569568199 zip
func4 = 0.00301686387516 izip
func5 = 0.00157338432678 % formatting
Run Code Online (Sandbox Code Playgroud)
这两个解决方案做的非常不同的事情.第一个循环以嵌套的方式,然后计算索引list.index,有效地使这成为一个双重嵌套的for循环,并需要你可以想到的125,000,000个操作.第二个以锁步方式迭代,在没有进行250000次操作的情况下进行500对.难怪他们是如此不同!
您是否熟悉Big O表示法来描述算法的复杂性?如果是这样,第一种解决方案是立方体,第二种解决方案是线性的.选择第一个在第二个上的成本将以惊人的速度增长a并且b变得更长,因此没有人会使用这样的算法.
就个人而言,我几乎肯定会使用像
', '.join('%s=%s' % pair for pair in itertools.izip(a, b))
Run Code Online (Sandbox Code Playgroud)
或者,如果我不是太担心的大小a和b和只写快,我会用zip代替itertools.izip.此代码有几个优点
这是线性的.尽管过早优化是一个巨大的问题,但最好不要使用具有不必要的渐近性能的算法.
这很简单,也很惯用.我看到其他人经常写这样的代码.
它的内存效率很高.通过使用生成器表达式而不是列表推导(itertools.izip而不是zip),我不在内存中构建不必要的列表,并将可能是O(n)(线性) - 内存操作变为O(1)(常量) - 记忆操作.
至于找到最快解决方案的时机,这几乎肯定是过早优化的一个例子.为了编写高性能程序,我们使用理论和经验编写高质量,可维护,良好的代码.经验表明,最好徒劳无功,最不利于停止随机操作并提出问题,"做这项特定操作的最佳方法是什么",并试图通过猜测甚至测试来确定它.
实际上,具有最佳性能的程序是使用最高质量的代码和非常有选择性的优化编写的程序.高质量的代码重视微基准测试的可读性和简单性,最终更容易测试,更少的错误和更好的重构 - 这些因素是有效优化程序的关键.您花费时间来修复不必要的错误,理解复杂的代码,以及重新分解的斗争可以花费在优化上.
当需要优化程序时 - 在经过测试并可能记录之后 - 这不是在随机片段上进行的,而是由实际使用情况和/或性能测试确定的,并通过分析收集测量结果.如果一段特定的代码仅占用程序的0.1%的时间,那么加速该部分的任何数量都不会带来任何真正的好处.