Here is my problem, I have to write a function that receives a string and returns that string with the characters between "*"
in uppercase, for example given that string: “I want *this text* to be uppercase”
, it returns : “I want THIS TEXT to be uppercase”
. Here is the code that I have written:
l = []
def func(s):
inside = False
for i in s:
if i == "*" and not inside:
inside = True
while inside:
if i == "*":
inside = False
else:
i.upper()
l.append(i)
print(s)
When I run the program it prints out the text without any change. What am I doing wrong? Thanks
I think you've tried to make this more complicated than it is. You need to find the index of both asterisks. From that you can get three slices of the original string and apply upper() to the slice between the asterisks. Note that this code will fail if there are fewer than two asterisks in the string.
def dotricks(s):
i = s.index('*')
j = s.index('*', i+i)
return s[0:i] + s[i+1:j].upper() + s[j+1:]
print(dotricks('I want *this text* to be uppercase'))
There are several issues here:
while
loop is pointless as i
is not incremented inside of iti
to i.upper()
The corrected code would be as follows:
l = []
def func(s):
inside = False
for i in s:
if i == "*" and not inside:
inside = True
while inside:
if i == "*":
inside = False
else:
i.upper()
if i != "*":
l.append(i)
return l
You are not changing the string in your code. In this edit below, I've assigned the letters of the string to a new variable. And used continue
to skip over the "*". Also, at the end your append will give you a list of letters which you need to use .join()
to concatentate.
Try this edit to your code, tested and working :
l = []
def func(s):
inside = False
temp = ""
for i in s:
if i == "*" and not inside:
inside = True
continue
if inside:
if i == "*":
inside = False
continue
else:
temp = i.upper()
else:
temp = i
l.append(temp)
new_string = "".join(l)
print(new_string)
return new_string
func("I want *this text* to be uppercase")
By splitting the string at the character *
then the uppercase entry is the odd one, then joining together. It is supposed that there are always an even number of *
so it should be considered a kind of reserved character.
s = "I want *this text* to be uppercase and *this* as well"
print(' '.join((j.upper() if i%2!=0 else j for i, j in enumerate(s.split('*')))))
Output
I want THIS TEXT to be uppercase and THIS as well
First, this function isn't doing anything to s
, so print(s)
will print whatever was input, unchanged.
Second, the while inside
loop needs to be outside of that if
statement - right now, it's only accessed when i
is an asterisk. Decrease that whole block's indent by one, and change while inside
to if inside
- that way, that code is executed for all values of i
when inside
is true.
Next, you need a way to signal when a second asterisk is reached, or a third, and so on. How about instead of assigning inside
to True
if i
is an asterisk and inside
is False, you swap the value of inside
every time an asterisk is reached?
if i == '*':
inside = not inside
This negates any need to mess with changing inside
in the second part of your code - it puts all the determining "am I inside/am I outside" logic in one place.
Next, you've declared a list l
outside the scope of the function, and it looks like you want to add the edited characters to it so the answer you want is in that list in the end. But you want your answer in a string, not a list, and it's usually bad practice to declare a list in global scope and then edit it during a function call (if you call the function more than once, the list will get messy!). Declare an empty string l = ''
at the beginning of the function, and then instead of appending characters to it, you can add them using the +=
operator.
You also need to make sure you're adding the uppercase version, l += i.upper()
or the regular version, l += i
, depending on whether or not inside
is true. You can put all the code after the if i == '*'
line in an else
statement to catch all cases that i
isn't an asterisk.
Putting it all together, your function can look something like this:
def func(s):
l = '' # the string that will be returned (the result of the function)
inside = False
for i in s:
if i == "*": # flip value of inside whenever you see an asterisk
inside = not inside
else: # otherwise, add i to the result
if inside:
l += i.upper() # uppercase if between two asterisks
else:
l += i # unchanged if not
return l # and return the modified string
Then, to test the function:
my_string = "I want *this text* to be uppercase"
my_string_modified = func(my_string)
print(my_string)
print(my_string_modified)
Output:
I want *this text* to be uppercase
I want THIS TEXT to be uppercase
There are definitely more "advanced" ways to do this, as pointed out in other answers on this post, but I hope this answer has helped to clarify what's going wrong in your code, how to fix it, and what some good practices are when you write this kind of thing. Writing code this way is, in my opinion, a really good way to understand how algorithmic processes can be designed and implemented. Happy coding!
I would leverage the power of the re
module:
import re
st = "I want *this text* to be uppercase and *this one*"
v = re.findall("\*(.*?)\*", st)
for s in v:
st = st.replace(f'*{s}*', s.upper())
print(st)
Output:
>>> I want THIS TEXT to be uppercase and THIS ONE
Anyway, re-editing your code:
def func(s):
l = []
inside = False
for i in s:
if i == "*":
inside = not inside # switch inside on/off when * is found
if inside:
i = i.upper() # upper the character if inside == True
l.append(i)
return l
If you look at your original code, part of the problem is in the following logic:
if i == "*" and not inside:
inside = True # inside is set to True when * is found....
while inside:
if i == "*":
inside = False # and immediately set to False again!
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.