8. anti_vowel [solved]


#1


I did the task and codecadamy said:

Oops, try again.
Your function fails on anti_vowel("Hey look Words!"). It returns "Hy lk Words!" when it should return "Hy lk Wrds!".

Where's the mistake?
Code below...

    liste = []
    for letter in text:
        liste.append(letter)
    for element in liste:
        if element == "a" or element == "e" or element == "o" or element == "i" or element == "u" or element == "A" or element == "O" or element == "E" or element == "I" or element == "U":
            liste.remove(element)
    stringliste = ""
    for i in liste:
        stringliste = stringliste + str(i)
    return stringlistepython



#2

Problem solved.
I added a "[:]" to the "for element in liste:" line.
New code:

def anti_vowel(text):
    liste = []
    for letter in text:
        liste.append(letter)
    for element in liste[:]:
        if element == "a" or element == "e" or element == "o" or element == "i" or element == "u" or element == "A" or element == "O" or element == "E" or element == "I" or element == "U":
            liste.remove(element)
    stringliste = ""
    for i in liste:
        stringliste = stringliste + str(i)
    return stringliste

#3

Just out of curiosity, what is the difference between looping over a list using:

for element in liste[:]:

and:

for element in liste:

seems to make a huge difference, but i don't understand it


#4

The point of the [:] is, to make the for-loop look cooler :open_mouth:


#5

But it also servers a function, take a look at this code:

def anti_vowel(text):
    liste = []
    for letter in text:
        liste.append(letter)
    for element in liste[:]:
        if element == "a" or element == "e" or element == "o" or element == "i" or element == "u" or element == "A" or element == "O" or element == "E" or element == "I" or element == "U":
            liste.remove(element)
    stringliste = ""
    for i in liste:
        stringliste = stringliste + str(i)
    return stringliste
print anti_vowel('Lets see real output')
def dual_vowel(text):
    liste = []
    for letter in text:
        liste.append(letter)
    for element in liste:
        if element == "a" or element == "e" or element == "o" or element == "i" or element == "u" or element == "A" or element == "O" or element == "E" or element == "I" or element == "U":
            liste.remove(element)
    stringliste = ""
    for i in liste:
        stringliste = stringliste + str(i)
    return stringliste
print dual_vowel('Lets see real output')

the ouput is different, i only removed [:] from the for loop


#6

I just realized it now too, didn't know that it would actually change something. I will look further into this, but for now I only found out that the [:] just copies the list, as far as I understand.

>>>squares = [1, 4, 9, 16, 25]
>>>squares[:]
>>>[1, 4, 9, 16, 25]

All slice operations return a new list containing the requested elements. This
means that the following slice returns a new (shallow) copy of the list.

https://docs.python.org/2/tutorial/introduction.html


#7

Ok now here is my theory:

If you use the for-loop, you also have some intern kind of counter to count each "round" it goes through.

So if we go through the program without [:]:

The program goes through each letter, so counter = 1, 2, 3, ....

When the letter (element) is a vocal, it gets removed, right? Let's say we go through the word "Lets", so the counter is currently on 2 for "e". If you remove the "e" from "Lets", the counter won't change, but the word itself gets shortened -> L (1) e (2) t (3) s (4) -> L (1) t (2) s (3) so it actually skips one letter. The only point where it would be trouble is if there are 2 vocals in a row, because if you skip a non-vocal it won't matter, since you skip it either way, but if you skip a vocal, you won't remove it.

Now you will ask why it works on the second program, let me explain:

The program still removes the vocals, but since the list is copied (as I told you before), it will remove the letters on the copy, and not on the original one, which it loops through. That's why the counter won't be affected by the removal of the vocals, since the list itself stays untouched :grin:


#8

Ah, i understand. But isn't then the reverse true? You loop through a copy of the list:

for element in liste[:]:

and remove the elements from the original list:

liste.remove(element)

but the counter is unaffected since it is looping over a copy of the lists. I do have to admit, it is clever. Thank you for you good explanation.


#9

I wasn't sure which way it actually was that's why I went with one of the possibilities ^^

And you're welcome, I actually learned about it thanks to you. Was very curious myself and that's why I thought through it a lot :grin:


#10

2 posts were split to a new topic: Is this code fast?


#11

I'm fairly new to programming myself but your code violates something called the DRY principle. I.e. Don't repeat yourself. There's more 'Pythonic' ways to go about it. Perhaps in future instead of writing or...or...or.... try defining all those elements in a single list like this:

vowels = ["A","a","E","e","I","i","O","o","U","u"]

def anti_vowel(text):
    letters = []
    for characters in text:
        letters.append(characters)
        for vowel in vowels:
            if vowel == characters:
                letters.remove(characters)
    return str("".join(letters))


print anti_vowel("Hey look Words!") # Prints "Hy lk Wrds"

#12

I believe liste[:] is same with liste[0:len(liste)]


#13

Yes ^^
We solved that mystery already :grin:


#16

6 posts were split to a new topic: anti_vowel question