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
CodePudding user response:
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))
CodePudding user response:
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.