This should be as fast as possible:
''.join([coder[i] if i in coder else i for i in text])
List comprehensions are much more optimized in Python compared to for loops which bear great overhead. I've passed a list comprehension as opposed to a generator in ''.join because it must know the length of it's input in advance before joining. If you give it a generator it has to make that into a list anyway (which is a bit slower).
Actually you can simplify this even further, which should be even faster
(this actually performs slower than the above method due to the method call)
''.join([coder.get(i,i) for i in text])
Timings:
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;')
Results:
''' Test 1 '''
5.0159105417 # applyCoder
3.41502481461 # listcomp1
4.76796932292 # listcomp2
''' Test 2 '''
34.9718502631 # applyCoder
22.0451702661 # listcomp1
34.1682597928 # listcomp2
It appears that the method call to coder.get completely negates the advantages of the list comprehension. I did predict it might be slower than listcomp1 because of this but I didn't think it would have this much of an impact. Anyway the list comprehension still wins.
Update:
If you modify list_comp2 like so:
def list_comp2(text, coder):
coder_get = coder.get
return ''.join([coder_get(i,i) for i in text])
The times improve drastically:
from 4.76796932292 (1st test) -> 3.95217394948
and 34.1682597928 (2nd test) -> 27.1162974624
returnstatement