Why doesn't this solution work for anti_vowel?


#1

def anti_vowel(text):
    text = list(text)
    for i in text:
        if i == "a" or i == "A" or i == "o" or i == "E" or i == "i" or i == "I" or i == "e" or i =="O" or i == "u" or i == "U":
            text.remove(i)
    text = "".join(text)
    return text

It returns 'Hy lk Words!'. Why does it remove the two o's in 'look' but not the o in 'words'?


#2

This line is the kicker. It is mutating the string you are iterating so is changing the position of elements. The .remove() method needs to be used in one-off situations where we know the index or the value in the element we wish to remove. Doing it in a loop will usually have unexpected consequences, as we see above.

The alternative is to start with an empty list, then append values that are not rejected.

    no_vowel = []
    for i in text:
        if i not in "aeiouAEIOU":
            no_vowel.append(i)
    return "".join(no_vowel)

#3

Supplemental

The basic definition of a string in most languages is as a primtive in an object wrapper. Text does not have any attributes. The wrapper object does.

This goes along with the general premise that it is immutable, or warrants being treated as such.

Given that, we should not be wanting to alter a string. If all we wish to do is iterate it, that's one thing, but to alter it requires a different process, and involves a temporary list object. That's why I did this the way it is represented above.


#4

Ok I understand now, thanks for the help!