'Reverse string without non letters symbol
I need to reverse only letters in each word. The order of the words and non-letter symbols must remain in their positions. I have a function, but it changes the position of the word.
def reverse_string(st):
stack = []
for el in st:
if el.isalpha():
stack.append(el)
result = ''
for el in st:
if el.isalpha():
result += stack.pop()
else:
result += el
return result
Input string:
b3ghcd hg#tyj%h
Expected output string:
d3chgb hj#ytg%h
Solution 1:[1]
You were really close! Your code is not working because you are applying the reversion to the whole string instead of doing it one word at a time. But just adding an extra step that splits the input string at white spaces (I assume white spaces is what defines words in your input) you'll get your desired result:
def reverse_string(st):
return ' '.join(reverse_word(word) for word in st.split())
def reverse_word(st):
stack = []
for el in st:
if el.isalpha():
stack.append(el)
result = ''
for el in st:
if el.isalpha():
result += stack.pop()
else:
result += el
return result
instr = 'b3ghcd hg#tyj%h'
print(reverse_string(instr)) # prints 'd3chgb hj#ytg%h'
NOTE:
You can pythonify your code a bit using some built in functions of list comprehension. In this case you'd replace the building of your stack.
stack = []
for el in st:
if el.isalpha():
stack.append(el)
for one of the following:
stack = [el for el in st if el.isalpha()]
or
stack = list(filter(str.isalpha, st))
Solution 2:[2]
Using the function you provided, one way of doing it is:
import re
def reverse_word(st):
stack = []
for el in st:
if el.isalpha():
stack.append(el)
result = ''
for el in st:
if el.isalpha():
result += stack.pop()
else:
result += el
return result
def reverse_string(st):
return re.sub(r'\S+', lambda match: reverse_word(match.group()), st)
print(reverse_string("b3ghcd hg#tyj%h"))
# "d3chgb hj#ytg%h"
Not thoroughly tested, and you might want to use for example [^\s,.?!;] or similar instead of \S, depending on what kind of 'sentences' you are dealing with.
Solution 3:[3]
Alternatively, you could try the following, which creates a reversed list of the alpha characters only, then inserts the non-alpha characters into their respective positions, and returns the sequence as a string.
def rev_str(s):
x = list(filter(str.isalpha, s[::-1]))
for i,s_ in enumerate(s):
if not s_.isalpha():
x.insert(i, s_)
return ''.join(x)
instr = 'b3ghcd hg#tyj%h'
outstr = ' '.join(rev_str(s) for s in instr.split())
print(outstr)
d3chgb hj#ytg%h
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | MikeM |
| Solution 3 | acrobat |
