use .replace() on only one character of a string with repetitive characters - python

I have this hangman problem and in this part, I'm trying to replace the placeholder '_ ' with the character that they've correctly guessed. e.g. if secretWord = 'lettuce', and they've guessed e, I want it to go through secretWord and check if e is in it, and then replace that '_ ' with e, so it returns
_ e_ _ _ _ e
my code goes:
create a placeholder string representation of secretWord
so Far = ''
for char in secretWord:
soFar = soFar + '_ '
check/replace the placeholder with the correct character
for char in secretWord:
if char in lettersGuessed:
soFar.replace('_ ', str(char))
print soFar
But in pythontutor.com, where secretWord = 'lettuce' and lettersGuessed = ['z', 'x', 'q', 'l', 'e', 't', 't', 'u', 'c', 'e'] my output was:
_ _ _ _ _ _ _
l l l l l l l
l l l l l l l
l l l l l l l
l l l l l l l
l l l l l l l
l l l l l l l
l l l l l l l
So basically, it saw that l was in letters guessed, and since it is supposed to replace '_ ' with that character, it replaced all of them. But I just want it to do it that once (and again, if it is in secretWord again). And then it couldn't replace any of the other characters because none of them were '_ '....

You don't want to use replace when you're trying to replace a character at a certain position; it's only for when you want to replace all characters, at all indexes, that match a certain value.
The way to replace a character at an index is with slicing:
soFar = soFar[:index] + newChar + soFar[index+1:]
In this case, each character in secretWord matches two characters in soFar, so you have to double those:
soFar = soFar[:index*2] + newChar + soFar[index*2+1:]
But how do you know the index? Not by calling index on the string—that will have the same problem, returning the index of the first character with that value, not the one you want. Use the enumerate function to keep count for you as you go along:
for index, char in enumerate(secretWord):
As kevinsa5 suggests, if you'd used a list instead of a string, you would make this simpler:
soFar = []
for char in secretWord:
soFar.append('_')
Now, the replacement is just:
soFar[index] = char
However, if you print that out as a string, it'll look like ['_', '_'] rather than _ _. To turn it into a nice string, you need to use the join method:
print ' '.join(soFar)

Use a list, rather than a string:
soFar = [char if char in lettersGuessed else '_' for char in secretWord]
print(' '.join(soFar))
Also, it would be better to have lettersGuessed be a set rather than a list. Since you care only about membership in the set, and it is appropriate for lettersGuessed to only contain unique items.

The way it is now, you are replacing every single '_' with the first guessed letter that appears in the secretWord. So, when the guessed l, it filled in every _ with l.
What you can do instead:
for index, char in enumerate(secretWord):
if char in lettersGuessed:
soFar = soFar[:index-1]+char+soFar[index+1:]
print soFar

Though abarnert has given you a neat solution already,
I approached this problem by tracking "unguessed_letters" and using "maketrans"
Solution:
from string import maketrans
def process_guess(secret_word, unguessed_letters, guess):
if guess in secret_word:
unguessed_letters = unguessed_letters.replace(guess, '')
trantab = maketrans(unguessed_letters, "_"*len(unguessed_letters))
return secret_word.translate(trantab), unguessed_letters
Usage Demonstration:
secret_word = "lettuce"
unguessed_letters = secret_word
lettersGuessed = ['z', 'x', 'q', 'l', 'e', 't', 't', 'u', 'c', 'e']
for i in lettersGuessed:
secret_mask, unguessed_letters = process_guess(secret_word, unguessed_letters, i)
print secret_mask
Execution Output:
$ python j.py
_______
_______
_______
l______
le____e
lett__e
lett__e
lettu_e
lettuce
lettuce

Related

Python function with list without any spaces

Define a function convert(input str) to return a list of characters based on the input
string input str. Specifically, each character in input str will be included as a separate element of
the returned list, while any spaces in input str will be ignored
def convert(input_str):
newlist = []
reallist = [char for char in input_str]
for k in input_str:
if k:
newlist.append(k)
return newlist
print(convert("Hi You"))
this gives output
['H', 'i', ' ', 'Y', 'o', 'u']
but I do not want the empty space between i and y
Instead of using a list comprehension and then filter the resulting list, you can do it in one step using if in the list comprehension:
def convert(input_str: str):
return [c for c in input_str if not c.isspace()]
print(convert("Hi You")) # ['H', 'i', 'Y', 'o', 'u']
Instead of using isspace, you could use [c for c in input_str if c != ' '] instead (although I believe using isspace is generally recommended).
you just need to add an if statement before you append an item to the list, only if char != " ": append char to new_list
def convert(input_str):
new_list = []
for char in input_str:
if char != " ": # <-----
new_list.append(char)
return new_list
print(convert("Hi You"))
def convert(input_str):
newstr = "".join(input_str.split())
reallist = [char for char in newstr]
return reallist
print(convert("Hi You"))
Maybe this if it is not just one space you are trying to skip
Python has built-in method for string that replaces string inside of string with another string. It takes the character that you want to replace and with what you want to replace it with as arguments.
def convert(input_str):
# Replace whitespaces with nothing
input_str = input_str.replace(" ", "")
new_list = [char for char in input_str]
return new_list
print(convert("Hi You"))

Trying to remove vowels from user input with function [duplicate]

I'm pretty sure my code is correct but it doesn't seem to returning the expected output:
input anti_vowel("Hey look words") --> outputs: "Hey lk wrds".
Apparently it's not working on the 'e', can anyone explain why?
def anti_vowel(c):
newstr = ""
vowels = ('a', 'e', 'i', 'o', 'u')
for x in c.lower():
if x in vowels:
newstr = c.replace(x, "")
return newstr
The function str.replace(old, new[, max]) don't changes c string itself (wrt to c you calls) just returns a new string which the occurrences of old have been replaced with new. So newstr just contains a string replaced by last vowel in c string that is the o and hence you are getting "Hey lk wrds" that is same as "Hey look words".replace('o', '').
I think you can simply write anti_vowel(c) as:
''.join([l for l in c if l not in vowels]);
What I am doing is iterating over string and if a letter is not a vowel then only include it into list(filters). After filtering I join back list as a string.
Why don't you do it with regexp? According to the documentation, something like this should work:
import re
def anti_vowel(s):
result = re.sub(r'[AEIOU]', '', s, flags=re.IGNORECASE)
return result
If you're using the function often, you could compile the regexp and use the compiled version.
Try String.translate.
>>> "Hey look words".translate(None, 'aeiouAEIOU')
'Hy lk wrds'
string.translate(s, table[, deletechars])
Delete all characters from s that are in deletechars (if present), and then translate the characters using table, which must be a 256-character string giving the translation for each character value, indexed by its ordinal. If table is None, then only the character deletion step is performed.
https://docs.python.org/2/library/string.html#string.Template.substitute
Or if you're using the newfangled Python 3:
>>> table = str.maketrans(dict.fromkeys('aeiouAEIOU'))
>>> "Hey look words.translate(table)
'Hy lk wrds'
Another option is to forego the vowel variable and put the char's to remove in the loop.
def anti_vowel(text):
for i in "aeiouAEIOU":
text = text.replace(i,"")
return text
print anti_vowel("HappIEAOy")
You should do this:
initialize newstr to c, and then
for x in c.lower():
if x in vowels:
newstr = newstr.replace(x, "")
That's because str.replace(old, new[, max]) returns the a copy of the string after replacing the characters:
The method replace() returns a copy of the string in which the
occurrences of old have been replaced with new, optionally restricting
the number of replacements to max.
So, this is the correct code:
def anti_vowel(c):
newstr = c
vowels = ('a', 'e', 'i', 'o', 'u')
for x in c.lower():
if x in vowels:
newstr = newstr.replace(x,"")
return newstr
You can also do it in a more pythonic way:
''.join([x for x in c if x not in vowels])
vowels = ('a', 'e', 'i', 'o', 'u', 'A', 'I', 'E', 'O', 'U')
for char in text:
if char in vowels:
text = text.replace(char, '')
return text
One more simpler way can be extracting the non-vowel characters from string and returning them.
def anti_vowel(text):
newstring=""
for i in text:
if i not in "aeiouAEIOU":
newstring=newstring+i
text=newstring
return text
I know there are many correct solutions on this subject but I thought to add few fun ways of solving this problem.
If you come from a C++/C# or Java, you will tend to use something like compare then action using the index to remove the unwanted entry in a for loop. Python has the Remove and Del functions. Remove function uses the value and
del uses the index.The pythonic solution is in the last function. Lets see how we can do that:
Here we are using the index in a for loop and del function very similar in C++:
def remove_vol(str1):
#list2 = list1 # this won't work bc list1 is the same as list2 meaning same container#
list1 = list(str1)
list2 = list(str1)
for i in range(len(list1)):
if list1[i] in volwes:
vol = list1[i]
x = list2.index(vol)
del list2[x]
print(list2)
Using the remove function:
def remove_vol(str1):
list1 = list(str1)
list2 = list(str1)
for i in list1:
if i in volwes:
list2.remove(i)
print(list2)
Building new string that does not contain the unwanted chars using their indexes:
def remove_vol(str1):
list1 = list(str1)
clean_str = ''
for i in range(len(list1)):
if list1[i] not in volwes:
clean_str += ''.join(list1[i])
print(clean_str)
Same as in the solution in above but using the value:
def remove_vol(str1):
list1 = list(str1)
clean_str = ''
for i in list1:
if i not in volwes:
clean_str += ''.join(i)
print(clean_str)
How you should do it in python? Using list comprehension! It is beautiful:
def remove_vol(list1):
clean_str = ''.join([x for x in list1 if x.lower() not in volwes])
print(clean_str)
def anti_vowel(text):
new=[]
vowels = ("aeiouAEIOU")
for i in text:
if i not in vowels:
new.append(i)
return ''.join(new)
i hope this helps..
def anti_vowel(text):
new_text = ""
for i in text:
if i == 'a' or i == 'A':
pass
elif i == 'e' or i == 'E':
pass
elif i == 'I' or i == 'i':
pass
elif i == 'o' or i == 'O':
pass
elif i == 'u' or i == 'U':
pass
else:
new_text = new_text + i
return new_text
print anti_vowel('Hey look Words!')
My implementation:
# Ask the user for input:
user_input = input("enter a string with some vowels: ")
print("input string: " + str(user_input))
vowels = ('a','e','i','o','u','A','E','I','O','U')
new_string="";
for i in range(0,len(user_input),1):
if user_input[i] in vowels:
print ('found a vowel, removing...')
else:
new_string+=user_input[i]
print("I've removed the vowels for you. You're welcome! The new string is: " + new_string)
A fairly simple approach could be;
def anti_vowel(text):
t = ''
for c in text:
if c in "aeiouAEIOU":
pass
else:
t += c
return t
def anti_vowel(text):
t=""
for c in text:
for i in "ieaouIEAOU":
if c==i:
c=""
else:
c=c
t=t+c
return t

How to search for each elements of a list in a string in python

let's say
there's a list
vowels = ['a', 'e', 'i', 'o', 'u']
x = raw_input("Enter something?")
Now how to find instances of these vowels in the x? I want to modify x so that it contains only non vowel letters.
.find won't work.
vowels = {'a', 'e', 'i', 'o', 'u'}
x =input('Enter...')
new_string = ''.join(c for c in x if c not in vowels)
Will create a new copy of x minus the vowels saved as new_string. I have changed vowels to be a set so that look up time is faster (somewhat trivial in this example but it's a good habit to sue where appropriate). Strings are immutable so you can't just take the letters out of x, you have to create a new string that is a copy of x without the values you don't need. .join() puts the whole thing back together.
You can use the count function for each letter. For example x.count('a') would count how many 'a' are in the word. The iterate over all the vowels and use sum to find the total number of vowels.
vowelCount = sum(x.count(vowel) for vowel in vowels)
from collections import Counter
vowels = {'a', 'e', 'i', 'o', 'u'}
s = "foobar"
print(sum(v for k,v in Counter(s).items() if k in vowels))
3
Or use dict.get with a default value of 0:
s = "foobar"
c = Counter(s)
print(sum(c.get(k,0) for k in vowels))
3
You can use like this,
>>> st = 'test test'
>>> len(re.findall('[aeiou]', st, re.IGNORECASE))
2
Or,
>>> vowels = ['a', 'e', 'i', 'o', 'u']
>>> sum(map(lambda x: vowels.count(x) if x in vowels else 0, st))
2
Or,
>>> len([ ch for ch in st if ch in vowels])
2

String manipulation in for loops

So I just learned how to manipulate single letters in a for loop from code academy.
But let's say I made a function and wanted this function to manipulate the vowels of an user inputted word and replace the vowel with four consecutive copies of itself. How would I go about that?
Expected output:
>>>Exclamation("car")
caaaar
>>>Exclamation("hello")
heeeelloooo
So far I have:
word = input("Enter a word: ")
vowels= ['a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U']
for char in word:
if char in vowels:
print(____,end='') #here I am unsure of how to replace it with consecutive copies of itself
else:
print(char,end='')
Your print statement can be:
print(4 * char,end='') # Or how many ever times you want to repeat it.
If word is 'car', this code:
>>> for char in word:
... if char in vowels:
... print(4 * char, end='')
... else:
... print(char, end='')
...
prints
caaaar
Note: You can include only the lower case vowels in your vowels list and in your if condition, check if char.lower() is in vowels.

Correct code to remove the vowels from a string in Python

I'm pretty sure my code is correct but it doesn't seem to returning the expected output:
input anti_vowel("Hey look words") --> outputs: "Hey lk wrds".
Apparently it's not working on the 'e', can anyone explain why?
def anti_vowel(c):
newstr = ""
vowels = ('a', 'e', 'i', 'o', 'u')
for x in c.lower():
if x in vowels:
newstr = c.replace(x, "")
return newstr
The function str.replace(old, new[, max]) don't changes c string itself (wrt to c you calls) just returns a new string which the occurrences of old have been replaced with new. So newstr just contains a string replaced by last vowel in c string that is the o and hence you are getting "Hey lk wrds" that is same as "Hey look words".replace('o', '').
I think you can simply write anti_vowel(c) as:
''.join([l for l in c if l not in vowels]);
What I am doing is iterating over string and if a letter is not a vowel then only include it into list(filters). After filtering I join back list as a string.
Why don't you do it with regexp? According to the documentation, something like this should work:
import re
def anti_vowel(s):
result = re.sub(r'[AEIOU]', '', s, flags=re.IGNORECASE)
return result
If you're using the function often, you could compile the regexp and use the compiled version.
Try String.translate.
>>> "Hey look words".translate(None, 'aeiouAEIOU')
'Hy lk wrds'
string.translate(s, table[, deletechars])
Delete all characters from s that are in deletechars (if present), and then translate the characters using table, which must be a 256-character string giving the translation for each character value, indexed by its ordinal. If table is None, then only the character deletion step is performed.
https://docs.python.org/2/library/string.html#string.Template.substitute
Or if you're using the newfangled Python 3:
>>> table = str.maketrans(dict.fromkeys('aeiouAEIOU'))
>>> "Hey look words.translate(table)
'Hy lk wrds'
Another option is to forego the vowel variable and put the char's to remove in the loop.
def anti_vowel(text):
for i in "aeiouAEIOU":
text = text.replace(i,"")
return text
print anti_vowel("HappIEAOy")
You should do this:
initialize newstr to c, and then
for x in c.lower():
if x in vowels:
newstr = newstr.replace(x, "")
That's because str.replace(old, new[, max]) returns the a copy of the string after replacing the characters:
The method replace() returns a copy of the string in which the
occurrences of old have been replaced with new, optionally restricting
the number of replacements to max.
So, this is the correct code:
def anti_vowel(c):
newstr = c
vowels = ('a', 'e', 'i', 'o', 'u')
for x in c.lower():
if x in vowels:
newstr = newstr.replace(x,"")
return newstr
You can also do it in a more pythonic way:
''.join([x for x in c if x not in vowels])
vowels = ('a', 'e', 'i', 'o', 'u', 'A', 'I', 'E', 'O', 'U')
for char in text:
if char in vowels:
text = text.replace(char, '')
return text
One more simpler way can be extracting the non-vowel characters from string and returning them.
def anti_vowel(text):
newstring=""
for i in text:
if i not in "aeiouAEIOU":
newstring=newstring+i
text=newstring
return text
I know there are many correct solutions on this subject but I thought to add few fun ways of solving this problem.
If you come from a C++/C# or Java, you will tend to use something like compare then action using the index to remove the unwanted entry in a for loop. Python has the Remove and Del functions. Remove function uses the value and
del uses the index.The pythonic solution is in the last function. Lets see how we can do that:
Here we are using the index in a for loop and del function very similar in C++:
def remove_vol(str1):
#list2 = list1 # this won't work bc list1 is the same as list2 meaning same container#
list1 = list(str1)
list2 = list(str1)
for i in range(len(list1)):
if list1[i] in volwes:
vol = list1[i]
x = list2.index(vol)
del list2[x]
print(list2)
Using the remove function:
def remove_vol(str1):
list1 = list(str1)
list2 = list(str1)
for i in list1:
if i in volwes:
list2.remove(i)
print(list2)
Building new string that does not contain the unwanted chars using their indexes:
def remove_vol(str1):
list1 = list(str1)
clean_str = ''
for i in range(len(list1)):
if list1[i] not in volwes:
clean_str += ''.join(list1[i])
print(clean_str)
Same as in the solution in above but using the value:
def remove_vol(str1):
list1 = list(str1)
clean_str = ''
for i in list1:
if i not in volwes:
clean_str += ''.join(i)
print(clean_str)
How you should do it in python? Using list comprehension! It is beautiful:
def remove_vol(list1):
clean_str = ''.join([x for x in list1 if x.lower() not in volwes])
print(clean_str)
def anti_vowel(text):
new=[]
vowels = ("aeiouAEIOU")
for i in text:
if i not in vowels:
new.append(i)
return ''.join(new)
i hope this helps..
def anti_vowel(text):
new_text = ""
for i in text:
if i == 'a' or i == 'A':
pass
elif i == 'e' or i == 'E':
pass
elif i == 'I' or i == 'i':
pass
elif i == 'o' or i == 'O':
pass
elif i == 'u' or i == 'U':
pass
else:
new_text = new_text + i
return new_text
print anti_vowel('Hey look Words!')
My implementation:
# Ask the user for input:
user_input = input("enter a string with some vowels: ")
print("input string: " + str(user_input))
vowels = ('a','e','i','o','u','A','E','I','O','U')
new_string="";
for i in range(0,len(user_input),1):
if user_input[i] in vowels:
print ('found a vowel, removing...')
else:
new_string+=user_input[i]
print("I've removed the vowels for you. You're welcome! The new string is: " + new_string)
A fairly simple approach could be;
def anti_vowel(text):
t = ''
for c in text:
if c in "aeiouAEIOU":
pass
else:
t += c
return t
def anti_vowel(text):
t=""
for c in text:
for i in "ieaouIEAOU":
if c==i:
c=""
else:
c=c
t=t+c
return t

Categories