4

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

1
  • Where is no_vowel defined? Commented Dec 11, 2016 at 5:18

4 Answers 4

9

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.

Sign up to request clarification or add additional context in comments.

4 Comments

Good answer but the last sentence is just not true. Always use a list comprehension when you use str.join. The argument for join will always be converted to a sequence so a generator expression is slower and as memory efficient as a list comprehension.
@MSeifert Do you have a reference to back that claim up?
the reference is the python source code for str.join: github.com/python/cpython/blob/master/Objects/…, see also my other comment
Yes, that "only" shows it's converted to a sequence. A generator is no sequence and converting a generator to a sequence is much slower than just creating a sequence in the first place.
5

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"))

Comments

2

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])

6 Comments

This doesn't work, it returns "['H', 'l', 'l', ' ', 'W', 'r', 'l', 'd']". This does: ''.join(c for c in text if c not in 'aeiouAEIOU')
You need to close off that string.
@leaf Because str.join needs a sequence (not a generator) so using a generator only adds needless overhead when it's converted to a list.
@MSeifert Perhaps your correct, but I'm still not really understating how using a generator is inefficient.
@leaf A generator is only useful if you don't need all elements or random access. You can check the source code (github.com/python/cpython/blob/master/Objects/…) and documentation (docs.python.org/3/c-api/sequence.html#c.PySequence_Fast). In this case that's equivalent to list(generator) which is definetly slower than doing a list comprehension.
|
1

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

3 Comments

This doesn't work, and results in a TypeError: translate() takes exactly one argument (2 given).
@Sybren This works in Python2.7, but in python3, the parameter deletechars of method translate is gone.
@Sybren re.sub('[aeiouAEIOU]', "", "Hello World") will work for both python2.7 and python3

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.