Weekly Challenge 313 Task 1
Reverse Letters: improving memory efficiency
The following was my entry for the Weekly Challenge 313 Task 1[1].
#!/usr/bin/env python3
def reverse_letters(string):
""" Given a string, reverse only the alphabetic characters in the string.
>>> reverse_letters('p-er?l')
'l-re?p'
>>> reverse_letters('wee-k!L-y')
'yLk-e!e-w'
>>> reverse_letters('_c-!h_all-en!g_e')
'_e-!g_nel-la!h_c'
"""
alpha_reversed = reversed([c for c in string if c.isalpha()])
return "".join(next(alpha_reversed) if c.isalpha() else c for c in string)
if __name__ == "__main__":
import doctest
doctest.testmod(verbose=True)
I was not 100% happy with this code because of the creation of an intermediate list for the call to reversed. At the time I couldn’t come up with a solution which would use a generator expression and therefore be more memory efficent.
While reviewing other peoples Python solutions I saw someone reverse the initial
string using string[::-1]
which I liked but later found out this is not
memory efficent for large strings as it creates a new string.
Finally, I found that I could just call reversed(string)
, enabling me to
iterate over the string in reverse order within a generator expression. My
revised solution for the task looks like this:
def reverse_letters(string):
alpha_iter = (c for c in reversed(string) if c.isalpha())
return "".join(next(alpha_iter) if c.isalpha() else c for c in string)