replace() function is not replacing 'e' character - python

My code should recognize the vowel letters and remove them from input string using the replace() function. However it works fine except for the 'e' letter.
If the input is "Hey look Words!" the output is "Hey lk Wrds!".
It identifies the 'e' only if if the "vowels" string is equal to "e" or "eE" only!
I am curious to know why?
def anti_vowel(text):
vowles="AaEeOoIiUu"
newstr=""
for i in text:
if i in vowles:
newstr=text.replace(i,"")
return newstr

You are placing only the last replacement result in newstr. All your previous str.replace() results are discarded.
For your input text Hey look Words!, the last vowel encountered is o so only o is replaced. The e replacement did take place and was stored in newstr but that value was then discarded when you set newstr to the result of the o replacement. It thus depends on the input string what vowel exactly will remain replaced; for the sentence 'The cat sat on the mat' it'll be a as that is the last vowel you test and replace.
Just loop directly over vowels and replace each of those characters; it is save to call str.replace() where the first argument is not present. Store the result back in text so that any subsequent replacements stick:
def anti_vowel(text):
vowels = "AaEeOoIiUu"
for vowel in vowels:
text = text.replace(vowel, "")
return text
Better still, use the str.translate() method to replace all vowels in one go:
# Python 2 version
def anti_vowel(text):
vowels = "AaEeOoIiUu"
return text.translate(None, vowels)
# Python 3 version
def anti_vowel(text):
vowels = str.maketrans(dict.fromkeys("AaEeOoIiUu"))
return text.translate(vowels)
str.translate() makes all replacements at once; the method changed between Python 2 str and Python 3 str, but in both versions all the vowels are ignored as the new string is built, without any further loops.

There's no reason to iterate through all the letters in the word; the replace() method does that for you. And you are erasing newstr every time, so by the end, all you're doing is replacing u. Here's what you need to do.
def anti_vowel(text):
vowels = "AaEeIiOoUu"
for i in vowels:
text = text.replace(i, "")
return text
This way, each time you replace text, you save and keep the replaced string. What you were doing earlier was making newstr into text without A, then replacing newstr with text sans a (but with A), so on and so forth. The end result was text without u but with everything else.

You should change your code to:
def anti_vowel(text):
vowles="AaEeOoIiUu"
newstr=text
for i in newstr:
if i in vowles:
newstr=newstr.replace(i,"")
return newstr
Then you will acummulate each replacement in your final string.
The way you are doing you always use the original string and replace only one group of chars ('Ee', 'Aa', etc...) in each iteration. So, in the end, you get a result of only one of these groups replaced in the original string.

Related

How to avoid .replace replacing a word that was already replaced

Given a string, I have to reverse every word, but keeping them in their places.
I tried:
def backward_string_by_word(text):
for word in text.split():
text = text.replace(word, word[::-1])
return text
But if I have the string Ciao oaiC, when it try to reverse the second word, it's identical to the first after beeing already reversed, so it replaces it again. How can I avoid this?
You can use join in one line plus generator expression:
text = "test abc 123"
text_reversed_words = " ".join(word[::-1] for word in text.split())
s.replace(x, y) is not the correct method to use here:
It does two things:
find x in s
replace it with y
But you do not really find anything here, since you already have the word you want to replace. The problem with that is that it starts searching for x from the beginning at the string each time, not at the position you are currently at, so it finds the word you have already replaced, not the one you want to replace next.
The simplest solution is to collect the reversed words in a list, and then build a new string out of this list by concatenating all reversed words. You can concatenate a list of strings and separate them with spaces by using ' '.join().
def backward_string_by_word(text):
reversed_words = []
for word in text.split():
reversed_words.append(word[::-1])
return ' '.join(reversed_words)
If you have understood this, you can also write it more concisely by skipping the intermediate list with a generator expression:
def backward_string_by_word(text):
return ' '.join(word[::-1] for word in text.split())
Splitting a string converts it to a list. You can just reassign each value of that list to the reverse of that item. See below:
text = "The cat tac in the hat"
def backwards(text):
split_word = text.split()
for i in range(len(split_word)):
split_word[i] = split_word[i][::-1]
return ' '.join(split_word)
print(backwards(text))

Removing characters from string Python

I'm trying to write a function that gets rid of the vowels in a given string, but it seems to not behave the way it should do...
def anti_vowel(text):
for c in text:
if c in "aeiouAEIOU":
no_vowel = text.replace(c, '')
return no_vowel
print(anti_vowel('Hello World')
so instead of printing
Hll Wrld
It prints
Hell Wrld
Thanks (in advance) for helping
The problem is that no_vowel only has the value of the last time that text.replace(c, '') was executed. Another issue is that no_vowel only gets a value when there is actually a vowel to remove; the code would fail on anti_vowel('vwllss'). Furthermore, you don't have to check whether a character is contained in the text before calling str.replace().
This should work:
def anti_vowel(text):
for vowel in "aeiouAEIOU":
text = text.replace(vowel, '')
return text
print(anti_vowel('Hello World'))
As others indicated, another approach would be to write code in a different way:
def anti_vowel(text):
''.join(c for c in text if c not in 'aeiouAEIOU')
Please do use a generator expression in ''.join() and not a list comprehension; such a list comprehension would allocate memory unnecessarily.
You can use string.translate() for this. For example:
def anti_vowel(text):
return text.translate(None, "aeiouAEIOU")
print(anti_vowel("hello world"))
With Python 3 the delete argument is gone, but you can still do it by mapping a character to None.
def anti_vowel_py3(text):
return text.translate({ord(i): None for i in "aeiouAEIOU"})
print(anti_vowel_py3("hello world"))
Your code doesnt work because every iteration you assign no_vowel with the text all over again and you iterate the text's letters what you shouldnt because replace already does it. You should write it like that:
def anti_vowel(text):
no_vowel = text
for c in 'aeiouAEIOU':
no_vowel = no_vowel.replace(c, '')
return no_vowel
Or, you could use a list comprehension. More Pythonic and faster to run:
def anti_vowel(text):
return ''.join([c for c in text if c not in 'aeiouAEIOU])
In every iteration of the loop, text is "Hello World", and the last vowel of text is "o", so at the end of the loop, no_vowel is "Hell Wrld".
In python2.7, use method translate instead. Here is the official document:
translate(...)
S.translate(table [,deletechars]) -> string
Return a copy of the string S, where all characters occurring
in the optional argument deletechars are removed, and the
remaining characters have been mapped through the given
translation table, which must be a string of length 256 or None.
If the table argument is None, no translation is applied and
the operation simply removes the characters in deletechars.
"Hello World".translate(None, "aeiouAEIOU") gives the correct result "Hll Wrld"
Also, re.sub('[aeiouAEIOU]', "", "Hello World") works for both python2.7 and python3

Unusual behaviour when using string concatenation inside for loop

So the code below properly removes all the vowels from a string as expected.
def disemvowel(string):
# Letters to remove & the new, vowerl free string
vowels_L = list('aeiouAEIOU')
new_string = ""
# Go through each word in the string
for word in string:
# Go through each character in the word
for character in word:
# Skip over vowels, include everything elses
if character in vowels_L:
pass
else:
new_string += character
# Put a space after every word
new_string += ' '
# Exclude space place at end of string
return new_string[:-1]
no_vowels = disemvowel('Nasty Comment: Stack exchange sucks!')
print(no_vowels)
>>>>python remove_vowels.py
>>>>Nsty Cmmnt: Stck xchng scks!
However, when I move the statement: "new_string+= ' '" to where I think it should be (I come from a C/C++ background), I end up getting a weird answer,
def disemvowel(string):
# Letters to remove & the new, vowerl free string
vowels_L = list('aeiouAEIOU')
new_string = ""
# Go through each word in the string
for word in string:
# Go through each character in the word
for character in word:
# Skip over vowels, include everything elses
if character in vowels_L:
pass
else:
new_string += character
# THIS IS THE LINE OF CODE THAT WAS MOVED
# Put a space after every word
new_string += ' '
# Exclude space place at end of string
return new_string[:-1]
no_vowels = disemvowel('Nasty Comment: Stack exchange sucks!')
print(no_vowels)
>>>>python remove_vowels.py
>>>>N s t y C m m n t : S t c k x c h n g s c k s !
Instead of placing a space after a word has finished being iterated over exclusively, a space is also place wherever there was a vowel. I was hoping someone would be able to explain why this occurs, even though in C the result would be quite different. Also, any suggestions to streamline/condense the could would be welcome! : )
for word in string doesn't iterate over the words; it iterates over the characters. You don't need to add spaces at all, because the spaces in the original string are preserved.
As interjay comments, your indentation is way out. Python relies on the indentation to describe which statements belong to what block, instead of the more common BEGIN ... END or { ... }.
In addition, user2357112 observes that you are expecting words from your string, whereas a string is simply a list of characters, and for word in string will set word to one character of string at a time
It is also much cleaner to use not in rather than an if together with a pass.
This is much closer to what you intended
def disemvowel(string):
# Letters to remove & the new, vowel-free string
vowels_list = 'aeiouAEIOU'
new_string = ""
# Go through each character in the string
for character in string:
# Skip over vowels, include everything else
if character not in vowels_list:
new_string += character
return new_string
print disemvowel('Nasty Comment: Stack exchange sucks!')
output
Nsty Cmmnt: Stck xchng scks!

How Do I Remove A Vowel From String [duplicate]

This question already has answers here:
Remove specific characters from a string
(2 answers)
Closed 8 years ago.
I'm trying to remove all the vowels from a string, using a function that is passed an argument called "text". I'm not sure if this is the most efficient way to code this, but it's all I could come up with. I'm not sure how to tell the function to check if "text" has any of the characters from the "vowels" list, and if so, to remove it. I thought replacing it with a space would do in the .replace() function would do the trick, but apparently not. The code is supposed to remove lower AND uppercase vowels, so I'm not sure if making them all lowercase is even acceptable. Thanks in advance.
def anti_vowel(text): #Function Definition
vowels = ['a','e','i','o','u'] #Letters to filter out
text = text.lower() #Convert string to lower case
for char in range(0,len(text)):
if char == vowels[0,4]:
text = text.replace(char,"")
else:
return text
Pretty simple using str.translate() (https://docs.python.org/2.7/library/stdtypes.html#str.translate)
return text.translate(None, 'aeiouAEIOU')
Python's Replace has you specify a substring to replace, not a position in the string. What you would want to do instead is
for char in range(0,5):
text = text.replace(vowels[char],"")
return text
UPDATED BASED ON COMMENT:
or you could do
for char in vowels:
text = text.replace(char,"");
return text;
Use the sub() function (https://docs.python.org/2/library/re.html#re.sub):
re.sub('[aeiou]', '', text)
Change your function to loop over the vowels list like this:
def anti_vowel(text): #Function Definition
vowels = ['a','e','i','o','u'] #Letters to filter out
text = text.lower() #Convert string to lower case
for vowel in vowels:
text = text.replace(vowel,"")
return text
This simply iterates over the vowels and replaces all occurrences of each vowel.

deleting letters from strings without string methods or imports?

This is a homework question. I need to define a function that takes a word and letter and deletes all occurrences of that letter in the word. I can't use stuff like regex or the string library. I've tried...
def delete(word,letter):
word = []
char = ""
if char != letter:
word+=char
return word
and
def delete(word,letter):
word = []
char = ""
if char != letter: #I also tried "if char not letter" for both
word = word.append(char)
return word
Both don't give any output. What am I doing wrong?
Well, look at your functions closely:
def delete(word,letter):
word = []
char = ""
if char != letter:
word+=char # or `word = word.append(char)` in 2nd version
return word
So, the function gets a word and a letter passed in. The first thing you do is throw away the word, because you are overwriting the local variable with a different value (a new empty list). Next, you are initializing an empty string char and compare its content (it’s empty) with the passed letter. If they are not equal, i.e. if letter is not an empty string, the empty string in char is added to the (empty list) word. And then word is returned.
Also note that you cannot add a string to a list. The + operation on lists is only implemented to combine two lists, so your append version is definitelly less wrong. Given that you want a string as a result, it makes more sense to just store the result as one to begin with.
Instead of adding an empty string to an empty string/list when something completely unrelated to the passed word happens, what you rather want to do is keep the original word intact and somehow look at each character. You basically want to loop through the word and keep all characters that are not the passed letter; something like this:
def delete(word, letter):
newWord = '' # let's not overwrite the passed word
for char in word:
# `char` is now each character of the original word.
# Here you now need to decide if you want to keep the
# character for `newWord` or not.
return newWord
The for var in something will basically take the sequence something and execute the loop body for each value of that sequence, identified using the variable var. Strings are sequences of characters, so the loop variable will contain a single character and the loop body is executed for each character within the string.
You're not doing anything with word passed to your function. Ultimately, you need to iterate over the word passed into your function (for character in word: doSomething_with_character) and build your output from that.
def delete(word, ch):
return filter(lambda c: c != ch, word)
Basically, just a linear pass over the string, dropping out letters that match ch.
filter takes a higher order function and an iterable. A string is an iterable and iterating over it iterates over the characters it contains. filter removes the elements from the iterable for which the higher order function returns False.
In this case, we filter out all characters that are equal to the passed ch argument.
I like the functional style #TC1 and #user2041448 that is worth understanding. Here's another implementation:
def delete( letter, string ):
s2 = []
for c in string:
if c!=letter:
s2.append( c )
return ''.join(s2)
Your first function uses + operator with a list which probably isn't the most appropriate choice. The + operator should probably be reserved for strings (and use .append() function with lists).
If the intent is to return a string, assign "" instead of [], and use + operators.
If the intent is to return a list of characters assign [], and use .append() function.
Change the name of the variable you are using to construct the returned value.
Assigning anything to word gets rid of the content that was given to the function as an argument.
so make it result=[] OR result="" etc..
ALSO:
the way you seem to be attempting to solve this requires you to loop over the characters in the original string, the code you posted does not loop at all.
you could use a for loop with this type of semantic:
for characterVar in stringVar:
controlled-code-here
code-after-loop
you can/should change the names of course, but i named them in a way that should help you understand. In your case stringVar would be replaced with word and you would append or add characterVar to result if it isn't the deleted character. Any code that you wish to be contained in the loop must be indented. the first unindented line following the control line indicates to python that the code comes AFTER the loop.
This is what I came up with:
def delete(word, letter):
new_word = ""
for i in word:
if i != letter:
new_word += i
return new_word

Categories

Resources