8. anti_vowel: Please help me to figure out what's wrong with my code!


#1

This is my code and I print out 2 examples to try to know what went wrong, but I still have no idea why it doesn't work. Can somebody help me out?


#2

You're changing the size of x while you iterate through it. That'll have effects on the loop that you'll have to account for.

Try iterating through a copy of x, or going backwards through x so that the removals have no effect on what the loop visits in the future. Or better yet, create a new empty list where you add only what you intend to keep. Removing is an expensive operation for lists (have to move the following elements to fill in the empty slot created by the removal) so this ends up being much faster


#3

Instead of:

x = list(text)

Try

x = []

This is something ionatan suggested but it may be unclear without an example. Good luck figuring it out from there!


#4

For me, changing x = [] to x = "" fixed it

def anti_vowel(text):
av = ""
for i in text:
    if i not in ('a' , 'e' , 'i' ,  'o' , 'u' , 'A' , 'E' , 'I' , 'O' , 'U'):
        av += i
print av #debugging purposes
return av

anti_vowel("Hey look Words!")


#5

I'll tell you how your code works :

You have a string stored in text. You have x which is a list of text. Now, for some n in x, if n is in the vowels tuple, it removes the particular letter hence changing the size of x.

What you can do?

def anti_vowel(text):
     x=list(text)
     y=x.copy()
     for n in y: #The Loop Iterates through x remains as it is
          if n in ('A','E','I','O','U','a','e','i','o','u'):
               x.remove(n) #If A vowel is found in y, it is removed from x. But y remains to be the original list
      return "".join(x)

#6

Thank you all for answering my questions! I appreciate that! Those advice are very very helpful!!!

However, I still don't get it why changing the size of x will cause some problems during iteration. For example, in my second tryout anti_vowel("OoOoOoOOoOoOoOoO"), I assume it will first run through the first 'O' and remove it. Then, even if the list has been changed, it still need to run through the next element, which is 'o', right? So in my assumption it will keep going through every element in the list regardless of the changing of the list. I just don't get the logic of the operation of Python... :cry:


#7

Thank you for your advice! But just one more question, why changing the size of x will have bad effect on iteration? Take anti_vowel("OoOoOoOOoOoOoOoOk") for example, after deleting the first "O", the rest of the list still has to be iterated through and the next "o" will be removed. Why would it be a problem?


#8

The first 'O' is at index 0
when you remove it, the first 'o' will move from index 1 to index 0

On the second iteration, the loop will visit index 1 which is the third character in the original string, since the string now looks like 'oOoO...'

The loop won't re-visit index 0 just because you removed something.

It's generally a bad idea to change the structure of something that you're currently iterating through!
And as mentioned, avoid removing anywhere but at the end of a list.


#9

Oh so that's how it works! Thank you so so much!!! You help me a lot!!
Thank you!!!!!!! :grinning:


#10

def anti_vowel(text):
b = list(text)
c = list(text)
a = ('a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U')
for d in c:
if d in a:
b.remove(d)
return ''.join(b)