Parsing a digit with int
is a bit slow and not needed here. You can use ord
instead. Then, you can just add ord('a')-ord('0')
which is 49. The result is:
new_s = ''.join(chr(ord(i)+49) for i in old_string)
For small strings, this is faster to generate a list so join
can be faster (because it know the size of the final string):
new_s = ''.join([chr(ord(i)+49) for i in old_string])
This is not a good idea for large strings since it requires more memory.
Note that map
is generally faster than basic generator expression. However, when it is combined with a lambda/function, it is slower than a generator expression (certainly due to the slow function call). Unfortunately, there is no builtin function to add 49 to all integers of the list here so the above last expression is likely the fastest.
Note that for loops are generally slower than generator expressions and comprehension lists. Iterative string concatenation make them even slower at pointed out by @FrankYellin in the comments.
Update 1:
An even faster solution is to encode/decode the string so to avoid calling ord
/chr
for each character separately (note that the previous comment about comprehension list still applies):
new_s = bytes([i+49 for i in old_string.encode()]).decode()
Update 2:
The solution provided by @KellyBundy seems the fastest on my machine:
prepared_table = str.maketrans('0123456789', 'abcdefghij')
new_s = old_string.translate(prepared_table)
Benchmark
Here is the results on my machine with your small input string:
for loop: 2.0 us
join + map + lambda + int: 2.0 us
join + generator-expr + int: 1.8 us
join + generator-expr + ord: 1.2 us
join + comprehension-list + ord: 1.0 us
encode/decode: 0.8 us
translate: 0.3 us (str.maketrans excluded)