Trying to replace text but the string is unchanged - python

Write a Python program to get a string from a given string where all occurrences of its first char have been changed to '$', except the first char itself
My code goes like this:
stringa = "restart"
def swaping(palavra):
prim = palavra[0]
for i in palavra:
if prim in palavra and prim not in palavra[0]:
palavra.replace(prim, "$")
return palavra
print(swaping(stringa))
It should have returned resta$t, but it returned the same form, restart.
Does anyone have an idea why it won't work? The sample solution is completely different from mine, they chose to split the string in two and bind them together in the end.

The reason why your string stayed the same is because the if statement always returns False:
prim in palavra is always True because prim is the first character in the string palavra.
prim not in palavra[0] is always False because prim is palavra[0], thus it is always in itself.
Combining them with an and clause and you'll get a False every time.
Also, str.replace will replace every occurence it finds (most of the times). There's no way to replace a character at a particular index in Python but to slice that string in half and do what your solution does.
Regardless, there's a simpler solution using str.replace:
def swapping(string):
return string[0] + string[1:].replace(string[0], '$')

Just a simple replace(), like this:
string = 'restart'
new_str = string.replace('r', '$').replace('$', 'r', 1)
new_str
Output:
'resta$t'

In your code as I can see it never be go into the if loop because prim not in palavra[0] gives always False as we assign prim = palavra[0], so your 'string' is not changed.
I suggest to use below code:
stringa = "restart"
def swaping(palavra):
prim = palavra[0]
palavra = ''.join([prim,palavra[1:].replace(prim,'$')])
return palavra
print(swaping(stringa))

you need to iterate through the string and match the occurrence of the first character with each element if matched then add $ in the resultant string else add the same character in the resultant string and return that resultant string
def func(string):
if len(string)<2:
return string
first = string[0]
result = first
for i, v in enumerate(string[1:]):
if v==first:
result+='$'
else:
result+=v
return result
result = func('restart')
print(result)
output
resta$t

Related

Can't wrap my head around how to remove a list of characters from another list

I've been able to isolate the list (or string) of characters I want excluded from a user entered string. But I don't see how to then remove all these unwanted characters. After I do this, I think I can try joining the user string so it all becomes one alphabet input like the instructions say.
Instructions:
Remove all non-alpha characters
Write a program that removes all non-alpha characters from the given input.
For example, if the input is:
-Hello, 1 world$!
the output should be:
Helloworld
My code:
userEntered = input()
makeList = userEntered.split()
def split(userEntered):
return list(userEntered)
if userEntered.isalnum() == False:
for i in userEntered:
if i.isalpha() == False:
#answer = userEntered[slice(userEntered.index(i))]
reference = split(userEntered)
excludeThis = i
print(excludeThis)
When I print excludeThis, I get this as my output:
-
,
1
$
!
So I think I might be on the right track. I need to figure it out how to get these characters out of the user input. Any help is appreciated.
Loop over the input string. If the character is alphabetic, add it to the result string.
userEntered = input()
result = ''
for char in userEntered:
if char.isalpha():
result += char
print(result)
This can also be done with a regular expression:
import re
userEntered = input()
result = re.sub(r'[^a-z]', '', userEntered, flags=re.I)
The regexp [^a-z] matches anything except an alphabetic character. The re.I flag makes it case-insensitive. These are all replaced with an empty string, which removes them.
There's basically two main parts to this: distinguish alpha from non-alpha, and get a string with only the former. If isalpha() is satisfactory for the former, then that leaves the latter. My understanding is that the solution that is considered most Pythonic would be to join a comprehension. This would like this:
''.join(char for char in userEntered if char.isalpha())
BTW, there are several places in the code where you are making it more complicated than it needs to be. In Python, you can iterate over strings, so there's no need to convert userEntered to a list. isalnum() checks whether the string is all alphanumeric, so it's rather irrelevant (alphanumeric includes digits). You shouldn't ever compare a boolean to True or False, just use the boolean. So, for instance, if i.isalpha() == False: can be simplified to just if not i.isalpha():.

If i in string but partial is even ok python

I am sure this is simple but I can't see or possibly can't find a solution.
Suppose I have a string, for example something--abcd--something and I want to find abcc in the string. I want to allow for one mismatch, meaning that the output of the below code should be True.
my_string='something--abcd--something'
substring = 'abcc'
if substring in my_string:
print('True')
else:
print('False')
I know that the substring is not in my_string but then what I want is to allow for one mismatch then the output will be True.
How can I achieve that?
There are certainly finer ways to do it, but one solution is to search for it with regexes in which one of the characters is replaced by a dot (or '\w' if you want the character to be a letter and nothing else).
We use a generator to lazily generate the regexes by replacing one of the letters each time, then check if any of these regexes match:
import re
def with_one_dot(s):
for i in range(len(s)):
yield s[:i] + '.' + s[i+1:]
def match_all_but_one(string, target):
return any(re.search(fuzzy_target, string) for fuzzy_target in with_one_dot(target))
def find_fuzzy(string, target):
" Return the start index of the fuzzy match, -1 if not found"
for fuzzy_target in with_one_dot(target):
m = re.search(fuzzy_target, string)
if m:
return m.start()
return -1
my_string = 'something--abcd--something'
print(match_all_but_one(my_string, 'abcc')) # 1 difference
# True
print(find_fuzzy(my_string, 'abcc'))
# 11
print(match_all_but_one(my_string,'abbb')) # 2 differences
# False
print(find_fuzzy(my_string, 'abbb'))
# -1
The with_one_dot(s) generator yields s with one letter replaced by a dot on each iteration:
for reg in with_one_dot('abcd'):
print(reg)
outputs:
.bcd
a.cd
ab.d
abc.
Each of these strings is used as a regex and tested on my_string. The dot . in a regex means 'match anything', so it allows any symbol instead of the original letter.
any returns True immediately if any of theses regexes matches, False if none does.

Index out of range for string of length 1

I am practicing recursive function for reversing a string.
Whenever there is no space between quotation marks in str1 == '', the code works fine.
However, if I do put a space in between the quotes in str1 == ' ', I get an error: String index out of range. (since both indices -1 and 0 are valid for str1 with space in quotes)
I do not understand why this error occurs and how to eliminate it.
def reverse(str1):
if str1 ==''
return str1
else:
return str1[-1]+reverse[:-1]
def main():
str1 = input ('Enter string')
result = reverse(str1)
print ('Reverse of string is ', result)
if __name__=='__main__':
main()
You could change reverse function like this:
return str1[::-1]
This will reverse irrespective of the length of string. Hope this works.
chars = [char for char in str1]
chars.reverse()
print(''.join(chars))
As Sam Stafford said in another answer and the comment from gilch, changing the base case and recursively calling the function on the string without the last character will allow the function to work. Something like:
def reverse(str1):
if len(str1) == 1:
return str1
else:
return str1[-1] + reverse(str1[:-1])
First: a semicolon is ;, a quotation mark is '. :)
The strings '' and ' ' are not the same -- one is an empty string, the other is a string that is one character long.
Your recursive function works by slicing the string into smaller and smaller pieces. Once it reaches an empty string, it needs to return instead of slicing it any further. This is called a "base case" -- a special check for the case that you can't solve by recursing further.
When you change your "base case" check so that it no longer catches the empty string (''), it breaks the function, because it will then continue on to attempt to slice, and that raises the exception you're seeing. The value of str1 that causes your function to break is '' (no space), and your recursion will always end in that value, so making this change to your code will always break it.

Python: if a word contains a digit

I'm writing a function that will take a word as a parameter and will look at each character and if there is a number in the word, it will return the word
This is my string that I will iterate through
'Let us look at pg11.'
and I want to look at each character in each word and if there is a digit in the word, I want to return the word just the way it is.
import string
def containsDigit(word):
for ch in word:
if ch == string.digits
return word
if any(ch.isdigit() for ch in word):
print word, 'contains a digit'
To make your code work use the in keyword (which will check if an item is in a sequence), add a colon after your if statement, and indent your return statement.
import string
def containsDigit(word):
for ch in word:
if ch in string.digits:
return word
Why not use Regex?
>>> import re
>>> word = "super1"
>>> if re.search("\d", word):
... print("y")
...
y
>>>
So, in your function, just do:
import re
def containsDigit(word):
if re.search("\d", word):
return word
print(containsDigit("super1"))
output:
'super1'
You are missing a colon:
for ch in word:
if ch.isdigit(): #<-- you are missing this colon
print "%s contains a digit" % word
return word
Often when you want to know if "something" contains "something_else" sets may be usefull.
digits = set('0123456789')
def containsDigit(word):
if set(word) & digits:
return word
print containsDigit('hello')
If you desperately want to use the string module. Here is the code:
import string
def search(raw_string):
for raw_array in string.digits:
for listed_digits in raw_array:
if listed_digits in raw_string:
return True
return False
If I run it in the shell here I get the wanted resuts. (True if contains. False if not)
>>> search("Give me 2 eggs")
True
>>> search("Sorry, I don't have any eggs.")
False
Code Break Down
This is how the code works
The string.digits is a string. If we loop through that string we get a list of the parent string broke down into pieces. Then we get a list containing every character in a string with'n a list. So, we have every single characters in the string! Now we loop over it again! Producing strings which we can see if the string given contains a digit because every single line of code inside the loop takes a step, changing the string we looped through. So, that means ever single line in the loop gets executed every time the variable changes. So, when we get to; for example 5. It agains execute the code but the variable in the loop is now changed to 5. It runs it agin and again and again until it finally got to the end of the string.

How do I ensure that a string will return properly in python?

I was building a bit of code that would trim off any non-digit entries from the start and end of a string, I had a very confusing issue with the following bit of code:
def String_Trim(Raw_String):
if Raw_String[0].isdigit() == False:
New_String = Raw_String[1:]
String_Trim(New_String)
elif Raw_String[-1].isdigit() == False:
New_String = Raw_String[:-1]
String_Trim(New_String)
else:
print Raw_String
return Raw_String
print(String_Trim('ab19fsd'))
The initial printing of Raw_String works fine and displays the value that I want (19), but for some reason, the last line trying to print the return value of String_Trim returns a None. What exactly is python doing here and how can I fix it? Any other comments about improving my code would also be greatly appreciated.
Use regex for this. Recursion for trimming a string is really not a good idea:
import re
def trim_string(string):
return re.sub(r'^([^0-9]+)(.*?)([^0-9]+)$', r'\2', string)
To break it down, the regex (r'^([^0-9]+)(.*?)([^0-9]+)$') is like so:
^ matches the start of a string.
([^0-9]+) matches a group of consecutive non-digit characters.
(.*?) matches a group of stuff (non-greedy).
([^0-9]+) matches another group of consecutive non-digit characters.
$ matches the end of the string.
The replacement string, r'\2', just says to replace the matched string with only the second group, which is the stuff between the two groups of non-digit characters.
But if you're really sure you want to use your existing solution, you need to understand how recursion actually works. When you call return foo, the function returns foo as its output. If you don't call return, you return None automatically.
That being said, you need to return in every case of the recursion process, not just at the end:
def String_Trim(Raw_String):
if Raw_String[0].isdigit() == False:
New_String = Raw_String[1:]
return String_Trim(New_String)
elif Raw_String[-1].isdigit() == False:
New_String = Raw_String[:-1]
return String_Trim(New_String)
else:
print Raw_String
return Raw_String
You return a value in only one case inside StringTrim. Add return in front of the recursive calls:
return String_Trim(New_String)
That should fix it.
If I understand your question correctly, you want to return only the digits from a string; because "trim of any non digits from the start and end" to me sounds like "return only numbers".
If that's correct, you can do this:
''.join(a for a in 'abc19def' if a.isdigit())

Categories