3

I am writing a function that removes all vowels from a word. It looks like this:

def remove_vowels(word):

    vowels = ['a', 'e', 'i', 'o', 'u']

    word = list(word)

    for letter in word:
        print('Looking for letter {}'.format(letter))

        if letter.lower() in vowels:
            try: 
                word.remove(letter)
            except ValueError:
                pass

    return ''.join(word)

I expect it to go through all the letters in the word, check each letter if it is in the vowels array and, if so, remove it.

However, it does not seem that it checks for all letters. For example, for the following call:

print(remove_vowels('perception'))

I am getting the following output:

Looking for letter p
Looking for letter e
Looking for letter c
Looking for letter e
Looking for letter t
Looking for letter i
Looking for letter n
prcpton

For some reason, it skips the r, the second p and the o. I am getting a similar result with other words. Why is this happening?

Stephen Rauch
  • 47,830
  • 31
  • 106
  • 135
Igor Skoldin
  • 730
  • 3
  • 12
  • 25
  • 2
    because `word.remove(letter)` removes vowel and you are iterating same `word` list. Now they have different `index` now. Try adding elements to new list. – sinsuren May 05 '17 at 04:23
  • Possible duplicate of [Remove items from a list while iterating](http://stackoverflow.com/questions/1207406/remove-items-from-a-list-while-iterating) – McGrady May 05 '17 at 04:26

4 Answers4

7

The reason why it didn't work before is during your for loop you are mutating word which means that it will skip over an iteration whenever you delete something because that deletion resulted in each letter moving up a position. That means that if there was a deletion at position 2 then the next item is now at position 2 and the item after it is in position 3 which is where the next iteration is.

def remove_vowels(word):

    vowels = ['a', 'e', 'i', 'o', 'u']

    word = list(word)
    print(word)
    new_word = []

    for letter in word:
        print('Looking for letter {}'.format(letter))

        if letter.lower() not in vowels:
            try: 
                new_word.append(letter)
            except ValueError:
                pass

    return ''.join(new_word)

print(remove_vowels('perception'))
Mike Tung
  • 4,735
  • 1
  • 17
  • 24
1

As mentioned in comments, working on the element you are iterating on, is often troublesome. How about this:

Code:

def remove_vowels(word):
    vowels = set('aeiou')
    return ''.join(l for l in word if l not in vowels)

Test Code:

print(remove_vowels('perception'))

Results:

prcptn
Stephen Rauch
  • 47,830
  • 31
  • 106
  • 135
  • Wow, that's concise. But I'm just learning Python so I will stick with easier to read a solution. – Igor Skoldin May 05 '17 at 04:39
  • @IgorSkoldin, thanks for the feedback, and yes you should definitely go with what you are comfortable with. However, my hearty recommendation, and the reason I post these solutions on beginner posts, is that you take the time to learn this syntax. It is not nearly as are hard as it initially looks, and it is ridiculously powerful. Cheers and good luck. – Stephen Rauch May 05 '17 at 04:51
0
def remove_vowels(word):

    vowels = ['a', 'e', 'i', 'o', 'u']

    word = list(word)
    result = list()
    for letter in word:
        print('Looking for letter {}'.format(letter))

        if letter.lower() not in vowels:
            try: 
                result.append(letter)
            except ValueError:
                pass

    return ''.join(result)


print(remove_vowels('perception')) 
Devendra Lattu
  • 2,732
  • 2
  • 18
  • 27
0
def remove_vowels(word):

vowels = ['a', 'e', 'i', 'o', 'u']

word = list(word)
word_new = []
for letter in word:
    print('Looking for letter {}'.format(letter))
    if letter.lower() in vowels:
        continue
    else:
        word_new.append(letter)

return ''.join(word_new)
print(remove_vowels('perception'))
R.A.Munna
  • 1,699
  • 1
  • 15
  • 29