For my programming class, I need to a create a program that takes in a string and two letters as an argument. Whenever the first letter appears in the string, it is replaced with the second letter. I can do this by making the final string into a list. However, our professor has stated that he wants it to be a string, not a list. The code shown below is what I used to make the program work if the final result was to appear in a list.
def str_translate_101(string, x, y):
new_list = []
for i in string:
if i == x:
new_list.append(y)
if i != x:
new_list.append(i)
return new_list
I tried to make one where it would output a string, but it would only return the first letter and the program would stop (which I'm assuming happens because of the "return")
def str_translate_101(string, old, new):
for i in string:
if i == old:
return new
else:
return i
I then tried using the print function, but that didn't help either, as nothing was outputted when I ran the function.
def str_translate_101(string, old, new):
for i in string:
if i == old:
print(new)
else:
print(i)
Any help would be appreciated.
An example of how the result should work when it works is like this:
str_translate_101('abcdcba', 'a', 'x') ---> 'xbcdcbx'
You can use join to merge a list into a string:
def str_translate_101(string, x, y):
new_list = []
for i in string:
if i == x:
new_list.append(y)
else:
new_list.append(i)
return ''.join(new_list)
or use the one-liner
str_tranlsate_101 = str.replace
The simplest solution would be, instead of storing the character in a list you can simply declare an empty string and in the 'if' block append the character to the string using the augmented '+=' operator. E.g.
if i == x:
concat_str += y
As for the return, basically, it will break out of the for loop and return to where the function was called from. This is because it only has 1 objective, which once achieved it will not bother to process any further code and simply go back to where the function was called from.
Related
My question is: is there any way i can somehow use all the returned capital letter indices and replace them ALL with an underscore? I wished to take the returned values from the uppercase_finder function and insert an underscore in front of those capitalized letters. However, when I run the program, I only get the first capital letter of input with an underscore. Can I somehow iterate all the returned uppercase indices into the part where I insert underscores?
def main():
first_input = input("input here: ")
uppercase_indice = uppercase_finder(first_input)
new_case = first_input[:uppercase_indice] + "_" + first_input[uppercase_indice:]
new_case = new_case.lower()
print(new_case)
def uppercase_finder(x):
for i in range(len(x)):
if x[i].isupper():
return i
main()
Okay so based on the assumption that the overall goal is to print out the string inputted all lowercase and an underscore appended to each letter that was uppercase.
You could iterate through each letter in the string without focusing on the indices at all. Something like:
def main():
first_input = input("input here: ")
updated_input = ""
for letter in first_input:
if(letter.isupper()):
updated_input += "_" + letter.lower()
else:
updated_input += letter
print(updated_input)
Output:
input here: HeLLo
_he_l_lo
Generally though if you want to stick with the uppercase_finder function, the return statement in the loop stops the loop the moment any letter that is uppercase is found. In order to get all of the indices of each letter that is uppercase you would need something like this:
def uppercase_finder(x):
list_of_indices = []
for i in range(len(x)):
if x[i].isupper():
list_of_indices.append(i)
return list_of_indices
Then in the main function you can iterate across the list:
for index in uppercase_indice:
# Make string manipulations for each index
It's obviously an assignment problem so I'm not going to spoon-feed the answer. But I can point out what's the problem in your uppercase_finder.
The problem is that it is returning the index as soon as it find the first upper case. What you can do is
def uppercase_finder(x):
uppercase_indices = []
for i in range(len(x)):
if x[i].isupper():
# Append the index to the list uppercase_indices
return uppercase_indices
There's some problem with your uppercase_finder function, 'return' denotes the end of a function, whenever a return is met, the function will immediately stop and exit with an returned value. For ur case, it seems u wanna return all the indices where there are a capital letter, u may use yield instead of return thus making the function a generator.
def uppercase_finder(x):
for i in range(len(x)):
if x[i].isupper():
yield i
use the output of a generator via a loop:
for capital_pos in uppercase_finder(first_input):
do_sth
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'm trying to grab every other letter from a string but i'm having some problem with print and return.
Why when i use print, the output is what i want and when i use return i only get the first letter?
string_bits(Hello) # Return string made of every other char starting with the first
def string_bits(str):
x = len(str)
for i in range(0,x,2):
print str[i]
output: H
l
o
vs
def string_bits(str):
x = len(str)
for i in range(0,x,2):
return str[i]
output: H
As everyone has pointed out, your function returns the instance on the first loop. You can use a temporary variable to store your result and return that result.
You can use the statement below inside a function:
return ''.join([ur_string[i] for i in range(0, len(ur_string), 2)])
Maybe what you want is this:
def string_bits(the_str):
x = len(the_str)
for i in range(0,x,2):
yield the_str[i]
or the_str[::2] takes only even position character
function 1
Here, you loop over the whole string and print each letter. The loop finishes when there are no more letters, and the function exits.
def string_bits(str):
x = len(str)
for i in range(0,x,2):
print str[i]
function 2
def string_bits(str):
x = len(str)
for i in range(0,x,2):
return str[i]
Here, you loop over the whole string, but instead of printing str[i] you are returning it. The return causes your function to exit, and so the loop doesn't continue on to the other letters.
Hope this helps!
This is because when you return, the program exits the function, whereas using print the program continues the loop.
As strings are iterable, you can use slicing to get the characters you want by specifying the step as 2:
To return a string:
def string_bits(s):
return s[::2]
To return a list of characters:
def string_bits(s):
return list(s[::2])
Alternatively, you could use yield to create a generator:
def string_bits(s):
for char in s[::2]:
yield char
Note: Goal of the function is to remove duplicate(repeated) characters.
Now for the same given recursive function, different output pops out for different argument:
def rd(x):
if x[0]==x[-1]:
return x
elif x[0]==x[1]:
return rd(x[1: ])
else:
return x[0]+rd(x[1: ])
print("Enter a sentence")
r=raw_input()
print("simplified: "+rd(r))
This functions works well for the argument only if the duplicate character is within the starting first six characters of the string, for example:
if r=abcdeeeeeeefghijk or if r=abcdeffffffghijk
but if the duplicate character is after the first six character then the output is same as the input,i.e, output=input. That means with the given below value of "r", the function doesn't work:
if r=abcdefggggggggghijkde (repeating characters are after the first six characters)
The reason you function don't work properly is you first if x[0]==x[-1], there you check the first and last character of the substring of the moment, but that leave pass many possibility like affffffa or asdkkkkkk for instance, let see why:
example 1: 'affffffa'
here is obvious right?
example 2: 'asdkkkkkk'
here we go for case 3 of your function, and then again
'a' +rd('sdkkkkkk')
'a'+'s' +rd('dkkkkkk')
'a'+'s'+'d' +rd('kkkkkk')
and when we are in 'kkkkkk' it stop because the first and last are the same
example 3: 'asdfhhhhf'
here is the same as example 2, in the recursion chain we arrive to fhhhhf and here the first and last are the same so it leave untouched
How to fix it?, simple, as other have show already, check for the length of the string first
def rd(x):
if len(x)<2: #if my string is 1 or less character long leave it untouched
return x
elif x[0]==x[1]:
return rd(x[1: ])
else:
return x[0]+rd(x[1: ])
here is alternative and iterative way of doing the same: you can use the unique_justseen recipe from itertools recipes
from itertools import groupby
from operator import itemgetter
def unique_justseen(iterable, key=None):
"List unique elements, preserving order. Remember only the element just seen."
# unique_justseen('AAAABBBCCDAABBB') --> A B C D A B
# unique_justseen('ABBCcAD', str.lower) --> A B C A D
return map(next, map(itemgetter(1), groupby(iterable, key)))
def clean(text):
return "".join(unique_justseen(text)
test
>>> clean("abcdefggggggggghijk")
'abcdefghijk'
>>> clean("abcdefghijkkkkkkkk")
'abcdefghijk'
>>> clean("abcdeffffffghijk")
'abcdefghijk'
>>>
and if you don't want to import anything, here is another way
def clean(text):
result=""
last=""
for c in text:
if c!=last:
last = c
result += c
return result
The only issue I found with you code was the first if statement. I assumed you used it to make sure that the string was at least 2 long. It can be done using string modifier len() in fact the whole function can but we will leave it recursive for OP sake.
def rd(x):
if len(x) < 2: #Modified to return if len < 2. accomplishes same as original code and more
return x
elif x[0]==x[1]:
return rd(x[1: ])
else:
return x[0]+rd(x[1: ])
r=raw_input("Enter a sentence: ")
print("simplified: "+rd(r))
I would however recommend not making the function recursive and instead mutating the original string as follows
from collections import OrderedDict
def rd(string):
#assuming order does matter we will use OrderedDict, no longer recursive
return "".join(OrderedDict.fromkeys(string)) #creates an empty ordered dict eg. ({a:None}), duplicate keys are removed because it is a dict
#grabs a list of all the keys in dict, keeps order because list is orderable
#joins all items in list with '', becomes string
#returns string
r=raw_input("Enter a sentence: ")
print("simplified: "+rd(r))
Your function is correct but, if you want to check the last letter, the function must be:
def rd(x):
if len(x)==1:
return x
elif x[0]==x[1]:
return rd(x[1: ])
else:
return x[0]+rd(x[1: ])
print("Enter a sentence")
r=raw_input()
print("simplified: "+rd(r))
I am trying to write a Python function that get a number as input and returns its reversed number as output. for example: 1234 returns 4321.
this is what I try, but it return only ''
def reverse(num):
L=[]
x=str(num)
L1=list(x)
for i in L1:
L.insert(0,i)
print 'the reversed num is:'
x=''
for i in L:
x.join(i)
return x
any ideas?
def reverse(num):
return str(num)[::-1]
or one line:
lambda x: str(x)[::-1]
Well, the easy solution is this one:
>>> int(str(1234)[::-1])
4321
Your code can be fixed by changing the part
for i in L:
x.join(i)
return x
to
for i in L:
x += i
return x
Alternatively, just replace that section by
return ''.join(L)
What was wrong with your code? Because of wrong indentation, you returned in the first iteration of the for loop. You never assigned a name to x.join(i) so the return value was lost. What you expected join to do I do not know.
First, there is an easier way by converting to string, slicing the string and converting it back to a number.
def reverse(num):
return int(str(num)[::-1])
Second, there are multiple errors in your code:
1) your return statement is in the loop, so it will return after the first iteration;
2) x does not change because x.join() creates a new string and does not modify the string x (which is immutable by the way)
3) no need to convert the string into a list since you can directly iterate over the string (for i in x: ...)
4) join() takes an iterator as an argument. No need for the second loop: return ''.join(L)
thank you all for the helpful ideas.
here is my solution:
def reverse(n):
reverse=0
while(n>0):
dig=n%10
reverse=reverse*10
reverse=reverse+dig
n=n/10
return reverse
def reverse(num)
return str(num)[::-1]
Reverse a string in Python
Other users already gave good answers. Here is a different one, for study purposes.
num = 1234
print "".join(reversed(str(num)))
# 4321
You can convert to int afterwards.