0
def anti_vowel(text):
    upper_vowels = ['A', 'E', 'I', 'O', 'U']
    lower_vowels = ['a', 'e', 'i', 'o', 'u']
    char_list = list(text)
    for char in char_list:
        if char in upper_vowels or char in lower_vowels:
            char_list.remove(char)
    new_word = ''
    for char in char_list:
        new_word += char
    return new_word

If I pass anti_vowel("Hey look Words!"), I get the result 'Hy lk Words!'. The 'o' in 'Words!' is not removed.

Leb
  • 15,483
  • 10
  • 56
  • 75
  • 7
    Don't modify `list`s as you're iterating through them. – TigerhawkT3 Jun 26 '15 at 06:17
  • You might take a look on a [similar question](http://stackoverflow.com/questions/3939361/remove-specific-characters-from-a-string-in-python). – albert Jun 26 '15 at 06:21
  • As you iterate through, you skip over the second o on the next iteration after you remove the first. Then on your next call to `char_list.remove(char)` you're actually removing the second `o` and not the 3rd. – Paul Rooney Jun 26 '15 at 06:25
  • `return ''.join(c for c in text if c.lower() not in {'a', 'e', 'i', 'o', 'u'})` – Peter Wood Jun 26 '15 at 06:35
  • @InvizTJ - You can accomplish this task in a much simpler way with a regular expression. Replace the entire body of your `anti_vowel(text)` function with this one line: `return re.sub( r'[aeiou]', '', text, 0, re.IGNORECASE )` – Michael Geary Jun 26 '15 at 06:39
  • Yes, that approach is present [here](http://stackoverflow.com/questions/21581824/correct-code-to-remove-the-vowels-from-a-string-in-python) and [here](http://stackoverflow.com/questions/7301292/string-replace-vowels-in-python). – TigerhawkT3 Jun 26 '15 at 06:40
  • 1
    @TigerhawkT3 - Ah, thanks. In fact, the function name and test string are identical in one of those too. I should have known it's a homework question! – Michael Geary Jun 26 '15 at 06:44

2 Answers2

3

As others have noted, you're modifying the list while you iterate over it. That's not going to work: the list changes size while you iterate, causing you to skip over some characters. You could use a list copy to avoid this, but maybe consider just using a better approach.

You can build the string up character-by-character, instead:

def anti_vowel(text):
    vowels = 'AEIOUaeiou'
    result = []
    for c in text:
        if c not in vowels:
            result.append(c)
    return ''.join(result)

This is faster, safer, shorter and easier to read than the original approach.

Alternately, you can use Python's powerful built-in string functions to do this very simply:

def anti_vowel(text):
    return text.translate(dict.fromkeys(map(ord, 'aeiouAEIOU')))

This pushes the text through a translation table that deletes all the vowels. Easy!

nneonneo
  • 171,345
  • 36
  • 312
  • 383
0

Few things going on here.

  • Never modify lists while iterating through them. Your could create a simple copy by calling list[:] instead if you'd to continue using your technique.
  • Use list comprehension to simplify your code further.

Simplifying the code a bit:

def anti_vowel(text):
    upper_vowels = ['A', 'E', 'I', 'O', 'U']
    lower_vowels = [s.lower() for s in upper_vowels]
    char_list = list(text)
    for char in char_list[:]:
        if char in upper_vowels or char in lower_vowels:
            char_list.remove(char)
    return ''.join(char_list)

If you want to simplify everything under a single lambda then use the following:

anti_vowel = lambda text: ''.join([s for s in text if s.upper() not in ['A', 'E', 'I', 'O', 'U']])

You can call it like regular function anti_vowel(). The idea behind it as follows:

  • Iterate through every character, taking the upper case
  • Use list comprehension to create a new list out of those characters, only if they do not exist in the vowels. ([x for x in list])
  • Finally put the characters together (''.join([])