0

Hi I'm doing the anti_vowel function, which basically takes out all of the vowels from the input. I'm confused about this code. Why doesn't it work? (For the last word "word") The output for "Hey look words!" is: Hy lk words! If anyone can help, thank you so so much!

def anti_vowel(text):
    l = []
    s = ""
    for i in text:
        l.append(i)

    for i in l:
        if i in "aeiouAEIOU":
            x = l.index(i)
            l.pop(x)
    print l
    print "".join(l)

anti_vowel("Hey look words!")

The output is: Hy lk Wrds!

xrz___
  • 3
  • 1
  • 4
    Don't _ever_ mutate a list as you iterate over it. – cs95 Jul 05 '17 at 00:44
  • 1
    Possible duplicate of [Modifying a Python dict while iterating over it](https://stackoverflow.com/questions/6777485/modifying-a-python-dict-while-iterating-over-it) – mwil.me Jul 05 '17 at 01:01
  • @mwil.me That is not the correct duplicate flag for this. If you want to find a duplicate that relates to this, it would have to be to explain modifying a *list* while iterating over it. That would be the direct problem here. – idjaw Jul 05 '17 at 01:03

5 Answers5

1

You're deleting elements from the list as you iterate over it. You're actually shortening the list before the loop can even reach the '...words' part.

A couple of other things. If you want to convert a string to a list, you can just do:

myList = list(myString)

Next, when iterating, do iterate over a copy of the list.

for i in l[:]:

The [:] operator creates a spliced copy, and iterates over that. This is the big fix, and it'll get your code running as expected. For that particular input, you get Hy lk wrds!.


Simpler alternative? Don't even use a list. You can work with strings, using the str.replace function:

def anti_vowel(text):
    newText = text[:]
    for i in 'aeiouAEIOU':
        newText = newText.replace(i, '')

    print(newText)
    return newText

newText = anti_vowel("Hey look words!")
print(newText)

Output:

Hy lk wrds!

An even simpler version? You can use str.translate:

>>> x = {c : '' for c in 'aeiouAEIOU'}
>>> "Hey look words!".translate(str.maketrans(x))
'Hy lk wrds!'
cs95
  • 379,657
  • 97
  • 704
  • 746
1

Modifying an iterator (your list) while looping over it will end up yielding very unexpected results, and should always be avoided. In your particular case, as you delete your list, you are actually reducing it, and therefore actually ending it "earlier" than you should.

What you should be doing instead is collecting your data in a new list based on what you are trying to filter. So, instead of popping, instead you should check for non-vowels and append to a new list. Taking your exact code and changing just that logic, you should be good:

def anti_vowel(text):
    l = []
    s = ""
    for i in text:
        l.append(i)
    new_l = []
    for i in l:
        if i not in "aeiouAEIOU":
            new_l.append(i)


    print("".join(new_l))

So, running that code now, will yield the following output:

Hy lk wrds!

Now, to go over some areas in your code where you are doing some unnecessary steps that you can simplify. You do not need to loop through your string like that and create a new list at the beginning of your function. Your string can already be iterated over, so simply do exactly that using your string. In other words you do not need this:

    l = []
    s = ""
    for i in text:
        l.append(i)

So, instead, you can just start from:

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

So, the above code now simply iterates over your string text, character-by-character, and we will check to make sure that each character does not match the vowels, and append it to our new list.

Finally, for the sake of really making this short. We can throw this in to a pretty little line making an expression that we can then call join on to create our string. Also! you don't need to check all cases since you can just keep your characters to a single casing by calling the lower method on your string you are iterating through to keep all under a single case, to make it simpler to check:

def anti_vowel(text):
    return ''.join(c for c in text if c.lower() not in "aeiou")

print(anti_vowel("Hey look words!"))
idjaw
  • 25,487
  • 7
  • 64
  • 83
1
def anti_vowel(text):
   new = ''
   for char in text:
     if char in "aeiou" or char in "AEIOU":
        ala = text.replace(char, '')

try doing this. Hope it helps

Afroz Chakure
  • 174
  • 1
  • 6
0

You should never alter an iterable (list in this case) while you're iterating over it. Bad things can and do happen.

Here's a different and a bit simpler way to do it. Instead of removing vowels from a list, instead, we create an empty list, and put the constants into it:

def anti_vowel(text):
    consts = []

    for letter in text:
        if letter not in "aeiouAEIOU":
            consts.append(letter)

    print "".join(consts)

anti_vowel("Hey look words!")

Output:

Hy lk wrds!
stevieb
  • 9,065
  • 3
  • 26
  • 36
0

Since other answers have already provided you with an explanation of your problem, and showed how to fix your code, I'll show you how you can make your function much smaller and cleaner.

You can use a generator comprehension to filter out all of the vowels from your input, and use ''.join() to join each individual character back together:

>>> def anti_vowels(text):
    return ''.join(c for c in text if c.lower() not in 'aeiou')

>>> anti_vowels('Hey look words!')
'Hy lk wrds!'
>>> anti_vowels('Hello, World!')
'Hll, Wrld!'
>>> anti_vowels('I love vowels!')
' lv vwls!'
>>> anti_vowels('Ronald Regan')
'Rnld Rgn'
>>> anti_vowels('Carts And BOxes')
'Crts nd Bxs'
>>> 

The important part of the comprehension is the the if part. It will only add the current character to the generator if it is not a vowel. I've also eliminated the extra uppercase vowels by using c.lower(). This force c to become lower case, so we can treat the character as if it were case insensitive.

You can also easily extend this to allow the user to specify the vowels they want to filter out (such as y):

>>> def anti_vowels(text, vowels='aeiou'):
    return ''.join(c for c in text if c.lower() not in vowels)

>>> anti_vowels('Hey look words!')
'Hy lk wrds!'
>>> anti_vowels('Hey look words!', vowels='aeiouy')
'H lk wrds!'
>>> 
Christian Dean
  • 22,138
  • 7
  • 54
  • 87