2

现在我使用一个列表来存储更改的字符串并使用 .join() 返回一个字符串

def applyCoder(text, coder):
    l = []
    for i in text:
        if i in coder:
            l.append(coder[i])
        else:
            l.append(i)
    return ''.join(l)

# example output, shifts all letters by 3 in a string
# print applyCoder("Hello, world!", buildCoder(3))
# buildCoder(3) returns dictionary, e.g. {'A': 'D', ...}
# >>> Khoor, zruog!

是否有更快的方法来更改和返回字符串?

4

1 回答 1

4

这应该尽可能快:

''.join([coder[i] if i in coder else i for i in text])

for与承受巨大开销的循环相比,Python 中的列表推导得到了更好的优化。我已经通过了列表理解而不是生成器,''.join因为它必须在加入之前提前知道输入的长度。如果你给它一个生成器,它无论如何都必须把它变成一个列表(这有点慢)。

实际上,您可以进一步简化它,应该更快由于方法调用,这实际上比上述方法执行得慢

''.join([coder.get(i,i) for i in text])

时间:

def applyCoder(text, coder):
    L = []
    for i in text:
        if i in coder:
            L.append(coder[i])
        else:
            L.append(i)
    return ''.join(L)

def list_comp(text, coder):
    return ''.join([coder[i] if i in coder else i for i in text])

def list_comp2(text, coder):
    return ''.join([coder.get(i,i) for i in text])

from timeit import timeit
from string import ascii_letters
d = dict(zip(ascii_letters, ascii_letters[3:] + ascii_letters[-3:]))


print timeit(stmt='applyCoder("Hello, world!", d)',
             setup='from __main__ import applyCoder, d;')

print timeit(stmt='list_comp("Hello, world!", d)',
             setup='from __main__ import list_comp, d;')    

print timeit(stmt='list_comp2("Hello, world!", d)',
             setup='from __main__ import list_comp2, d;')

print timeit(stmt='applyCoder("Hello, world!"*10, d)',
             setup='from __main__ import applyCoder, d;')

print timeit(stmt='list_comp("Hello, world!"*10, d)',
             setup='from __main__ import list_comp, d;')


print timeit(stmt='list_comp2("Hello, world!"*10, d)',
             setup='from __main__ import list_comp2, d;')

结果:

''' Test 1 '''
5.0159105417    # applyCoder
3.41502481461   # listcomp1
4.76796932292   # listcomp2

''' Test 2 '''
34.9718502631   # applyCoder
22.0451702661   # listcomp1
34.1682597928   # listcomp2

似乎该方法调用coder.get完全否定了列表理解的优点。我确实预测它可能会因此而变慢listcomp1,但我认为它不会产生如此大的影响。无论如何,列表理解仍然获胜。

更新: 如果你list_comp2这样修改:

def list_comp2(text, coder):
    coder_get = coder.get
    return ''.join([coder_get(i,i) for i in text])

时代进步很大:

4.76796932292(第一次测试)->3.95217394948

34.1682597928(第二次测试)->27.1162974624

于 2013-04-18T08:37:59.213 回答