First of all, I know -= operation doesn't work in str.
But is there a function that works the same?
The reason why I need this is because
def function(self, str_source):
str_source = str_source[:-1] # removing last character of the string
str_source += self.other_function() # adding other characters
return True
In this sort of function, when I do s = s[:-1], the original string does not change.
I know why it does not change, and I know I can just return another modified string, but I am currently working on someone else's code that I can't complete rip up the Project.
So is it possible to remove the substring of a string in a function?
There is no way to change the original string in python. If you want to cuts last characters then prodouce a new string.
For more Details
-= is an assignment operator and assignment operators use for some arithmetic or logical operation.
Here's a hack:
import sys
def function(str_source):
# get existing value
gvars = sys._getframe(1).f_globals
lvars = sys._getframe(1).f_locals
if str_source in lvars:
dir = lvars
elif sttr_source in gvars:
dir = gvars
else:
# might want to raise an exception here
print(str_source, "not found")
return False
ext_str = str(dir[str_source])
ext_str = ext_str[:-1] # removing last character of the string
# Store
dir[str_source] = ext_str
return True
s1 = "hello"
function("s1")
s2 = "world"
function("s2")
print(s1)
print(s2)
Gives:
hell
worl
Related
"Given a string of both letters and special characters/numbers, use recursion to concatenate the letters into a single string and return it."
My code is below, I'm still learning recursion and am stuck in trying to trace it. I tried a bunch of different lines in this code but idk how to fix what I do have so far:
def decoder(encryptedStr):
if len(encryptedStr) != 0:
if encryptedStr[0].isalpha() == True:
decoded = encryptedStr[0]
decoded.join(decoder(encryptedStr[1:]))
print(decoded)
else:
decoder(encryptedStr[1:])
I haven't had it return anything yet because I'm struggling with the part where I have to join the new letters to the output string. Instead of .join I also tried:
decoded += decoder(encryptedStr[1:])
but it doesn't work bc Nonetype??
Your main issue is that you didnt return, but there are some issues with your approach that make this more complex than need-be.
Think tail-first when doing recursion- What is your end condition, and how do you decide to continue. Typically with this kind of method you do something like, 1) process a single value in the list, 2) let the recursive method handle the rest of it, 3) combine the results.
An easy indicator of the tail-first return here would be to return nothing if the string is empty:
def decoder(encryptedStr):
if len(encryptedStr) == 0:
return ""
...
Now in each run we want to operate on one letter and pass the rest to a recursive call. Ignoring the special character requirement, you'd get something like this:
def decoder(encryptedStr):
if len(encryptedStr) == 0:
return ""
first = encryptedStr[0]
rest = decoder(encryptedStr[1:])
return first + rest
Now we can handle the special case where we want to omit letters.
def decoder(encryptedStr):
if len(encryptedStr) == 0:
return ""
first = encryptedStr[0]
rest = decoder(encryptedStr[1:])
if not first.isalpha():
first = ""
return first + rest
And that's all there is to it!
Bonus for some refactoring:
def clean(letter):
return letter if letter.isalpha() else ""
def decoder(encrypted):
if len(encrypted) == 0:
return ""
return clean(encrypted[0]) + decoder(encrypted[1:])
There's a bunch of problems here:
I don't think join does what you want it to do in that case. If you want to add some strings together simply use +=. join would insert decoded character between whatever decoder(encryptedStr[1:]) returns.
You don't have a case for len(encryptedStr) == 0, so it returns default value of None. That's why you cannot append it's results to decoded.
Return immediately if there is nothing to do. Otherwise take the first letter if it matches the condition and add the result of the recursive call (where the parameter is the current encrypted string without the first character).
def decoder(encrypted):
if not encrypted:
return ''
decrypted = encrypted[0] if encrypted[0].isalpha() else ''
return decrypted + decoder(encrypted[1:])
print(decoder('Abc123rtZ5'))
The result is AbcrtZ.
Bonus info (as #JonSG mentioned in the comments):
Run this with print(decoder('A' * 1000)) and you'll see why recursion is a bad idea for this task.
Every recursive function must have a base condition that stops the recursion or else the function calls itself infinitely.
To recursively concatenate ONLY the letters of an input string into a single output string:
some_string = "I2L4o2v3e+P;y|t!o#n"
def decoder(encryptedStr, decoded = ""):
if len(encryptedStr) == 0: # Base condition
return decoded
if encryptedStr[0].isalpha():
decoded += encryptedStr[0]
return decoder(encryptedStr[1:], decoded)
# If the char in the index [0] is not a letter it will be sliced out.
return decoder(encryptedStr[1:], decoded)
print(decoder(some_string))
Output:
ILovePython
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?
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.
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'))
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")
There are several issues here:
You don't return anything inside your function
Your while loop is pointless as i is not incremented inside of it
You need to assign i to i.upper()
You need to convey the input to a list
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
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!
I want to use recursion to reverse a string in python so it displays the characters backwards (i.e "Hello" will become "olleh"/"o l l e h".
I wrote one that does it iteratively:
def Reverse( s ):
result = ""
n = 0
start = 0
while ( s[n:] != "" ):
while ( s[n:] != "" and s[n] != ' ' ):
n = n + 1
result = s[ start: n ] + " " + result
start = n
return result
But how exactly do I do this recursively? I am confused on this part, especially because I don't work with python and recursion much.
Any help would be appreciated.
def rreverse(s):
if s == "":
return s
else:
return rreverse(s[1:]) + s[0]
(Very few people do heavy recursive processing in Python, the language wasn't designed for it.)
To solve a problem recursively, find a trivial case that is easy to solve, and figure out how to get to that trivial case by breaking the problem down into simpler and simpler versions of itself.
What is the first thing you do in reversing a string? Literally the first thing? You get the last character of the string, right?
So the reverse of a string is the last character, followed by the reverse of everything but the last character, which is where the recursion comes in. The last character of a string can be written as x[-1] while everything but the last character is x[:-1].
Now, how do you "bottom out"? That is, what is the trivial case you can solve without recursion? One answer is the one-character string, which is the same forward and reversed. So if you get a one-character string, you are done.
But the empty string is even more trivial, and someone might actually pass that in to your function, so we should probably use that instead. A one-character string can, after all, also be broken down into the last character and everything but the last character; it's just that everything but the last character is the empty string. So if we handle the empty string by just returning it, we're set.
Put it all together and you get:
def backward(text):
if text == "":
return text
else:
return text[-1] + backward(text[:-1])
Or in one line:
backward = lambda t: t[-1] + backward(t[:-1]) if t else t
As others have pointed out, this is not the way you would usually do this in Python. An iterative solution is going to be faster, and using slicing to do it is going to be faster still.
Additionally, Python imposes a limit on stack size, and there's no tail call optimization, so a recursive solution would be limited to reversing strings of only about a thousand characters. You can increase Python's stack size, but there would still be a fixed limit, while other solutions can always handle a string of any length.
I just want to add some explanations based on Fred Foo's answer.
Let's say we have a string called 'abc', and we want to return its reverse which should be 'cba'.
def reverse(s):
if s == "":
return s
else:
return reverse(s[1:]) + s[0]
s = "abc"
print (reverse(s))
How this code works is that:
when we call the function
reverse('abc') #s = abc
=reverse('bc') + 'a' #s[1:] = bc s[0] = a
=reverse('c') + 'b' + 'a' #s[1:] = c s[0] = a
=reverse('') + 'c' + 'b' + 'a'
='cba'
If this isn't just a homework question and you're actually trying to reverse a string for some greater goal, just do s[::-1].
def reverse_string(s):
if s: return s[-1] + reverse_string(s[0:-1])
else: return s
or
def reverse_string(s):
return s[-1] + reverse_string(s[0:-1]) if s else s
I know it's too late to answer original question and there are multiple better ways which are answered here already. My answer is for documentation purpose in case someone is trying to implement tail recursion for string reversal.
def tail_rev(in_string,rev_string):
if in_string=='':
return rev_string
else:
rev_string+=in_string[-1]
return tail_rev(in_string[:-1],rev_string)
in_string=input("Enter String: ")
rev_string=tail_rev(in_string,'')
print(f"Reverse of {in_string} is {rev_string}")
s = input("Enter your string: ")
def rev(s):
if len(s) == 1:
print(s[0])
exit()
else:
#print the last char in string
#end="" prints all chars in string on same line
print(s[-1], end="")
"""Next line replaces whole string with same
string, but with 1 char less"""
return rev(s.replace(s, s[:-1]))
rev(s)
if you do not want to return response than you can use this solution. This question is part of LeetCode.
class Solution:
i = 0
def reverseString(self, s: List[str]) -> None:
"""
Do not return anything, modify s in-place instead.
"""
if self.i >= (len(s)//2):
return
s[self.i], s[len(s)-self.i-1] = s[len(s)-self.i-1], s[self.i]
self.i += 1
self.reverseString(s)
My goal is to have the function SRA_Accession return it's values as a string e.g "Value1,Value2,Value3" the code so far is
def SRA_Accession():
SRA=1293518
while (SRA < 1293618):
SRA=SRA+1
print "SRA"+str(SRA)
if False:
break
the lack of tabs are making this not work and you need a return statement which returns everything.
def SRA_Accession():
SRA=1293518
my_list = []
while (SRA < 1293618):
SRA=SRA+1
my_list.append("SRA"+str(SRA))
return ','.join(my_list)
Judging by the way you are writing the statement I would say you were looking to use a yield statement which returns each SRA string all by itself. This means you will need to add commas outside the function like so.
def SRA_Accession():
SRA=1293518
while (SRA < 1293618):
SRA=SRA+1
yield "SRA"+str(SRA)
value = ','.join(list(SRA_Accession()))
print(value)
I want to use recursion to reverse a string in python so it displays the characters backwards (i.e "Hello" will become "olleh"/"o l l e h".
I wrote one that does it iteratively:
def Reverse( s ):
result = ""
n = 0
start = 0
while ( s[n:] != "" ):
while ( s[n:] != "" and s[n] != ' ' ):
n = n + 1
result = s[ start: n ] + " " + result
start = n
return result
But how exactly do I do this recursively? I am confused on this part, especially because I don't work with python and recursion much.
Any help would be appreciated.
def rreverse(s):
if s == "":
return s
else:
return rreverse(s[1:]) + s[0]
(Very few people do heavy recursive processing in Python, the language wasn't designed for it.)
To solve a problem recursively, find a trivial case that is easy to solve, and figure out how to get to that trivial case by breaking the problem down into simpler and simpler versions of itself.
What is the first thing you do in reversing a string? Literally the first thing? You get the last character of the string, right?
So the reverse of a string is the last character, followed by the reverse of everything but the last character, which is where the recursion comes in. The last character of a string can be written as x[-1] while everything but the last character is x[:-1].
Now, how do you "bottom out"? That is, what is the trivial case you can solve without recursion? One answer is the one-character string, which is the same forward and reversed. So if you get a one-character string, you are done.
But the empty string is even more trivial, and someone might actually pass that in to your function, so we should probably use that instead. A one-character string can, after all, also be broken down into the last character and everything but the last character; it's just that everything but the last character is the empty string. So if we handle the empty string by just returning it, we're set.
Put it all together and you get:
def backward(text):
if text == "":
return text
else:
return text[-1] + backward(text[:-1])
Or in one line:
backward = lambda t: t[-1] + backward(t[:-1]) if t else t
As others have pointed out, this is not the way you would usually do this in Python. An iterative solution is going to be faster, and using slicing to do it is going to be faster still.
Additionally, Python imposes a limit on stack size, and there's no tail call optimization, so a recursive solution would be limited to reversing strings of only about a thousand characters. You can increase Python's stack size, but there would still be a fixed limit, while other solutions can always handle a string of any length.
I just want to add some explanations based on Fred Foo's answer.
Let's say we have a string called 'abc', and we want to return its reverse which should be 'cba'.
def reverse(s):
if s == "":
return s
else:
return reverse(s[1:]) + s[0]
s = "abc"
print (reverse(s))
How this code works is that:
when we call the function
reverse('abc') #s = abc
=reverse('bc') + 'a' #s[1:] = bc s[0] = a
=reverse('c') + 'b' + 'a' #s[1:] = c s[0] = a
=reverse('') + 'c' + 'b' + 'a'
='cba'
If this isn't just a homework question and you're actually trying to reverse a string for some greater goal, just do s[::-1].
def reverse_string(s):
if s: return s[-1] + reverse_string(s[0:-1])
else: return s
or
def reverse_string(s):
return s[-1] + reverse_string(s[0:-1]) if s else s
I know it's too late to answer original question and there are multiple better ways which are answered here already. My answer is for documentation purpose in case someone is trying to implement tail recursion for string reversal.
def tail_rev(in_string,rev_string):
if in_string=='':
return rev_string
else:
rev_string+=in_string[-1]
return tail_rev(in_string[:-1],rev_string)
in_string=input("Enter String: ")
rev_string=tail_rev(in_string,'')
print(f"Reverse of {in_string} is {rev_string}")
s = input("Enter your string: ")
def rev(s):
if len(s) == 1:
print(s[0])
exit()
else:
#print the last char in string
#end="" prints all chars in string on same line
print(s[-1], end="")
"""Next line replaces whole string with same
string, but with 1 char less"""
return rev(s.replace(s, s[:-1]))
rev(s)
if you do not want to return response than you can use this solution. This question is part of LeetCode.
class Solution:
i = 0
def reverseString(self, s: List[str]) -> None:
"""
Do not return anything, modify s in-place instead.
"""
if self.i >= (len(s)//2):
return
s[self.i], s[len(s)-self.i-1] = s[len(s)-self.i-1], s[self.i]
self.i += 1
self.reverseString(s)