Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Python Python Collections (2016, retired 2019) Lists Disemvowel

Abdulkadir Kollere
Abdulkadir Kollere
1,723 Points

Disemvowel function not giving right output

In workspaces, when I put in a word the function returns it with all the vowels removed. However it does not allow me to complete the challenge. Any help will be appreciated.

disemvowel.py
def disemvowel(word):
    vowels = ['a', 'e', 'i', 'o', 'u']
    new = list(word.lower())
    final_output = list(word.lower())
    for letter in new:
        if letter in vowels:
            final_output.remove(letter)

            word = final_output
    return word
    print(word)

print(disemvowel('tree'))

1 Answer

Chris Freeman
MOD
Chris Freeman
Treehouse Moderator 68,441 Points

The function needs to handle removing uppercase vowels, but should leave the uppercase non-vowels unchanged. One way is to not us lower() on new and final_output. Instead only lower the letter at comparison time.

Also, the returned value needs to be joined back to a single string.

def disemvowel(word):
    vowels = ['a', 'e', 'i', 'o', 'u']
    new = list(word)
    final_output = list(word)
    for letter in new:
        if letter.lower() in vowels:
            final_output.remove(letter)           
            word = "".join(final_output)
    return word

It's good you are avoiding modifying the looped over iterable. You can use a temporary copy to compact the code:

def disemvowel(word):
    vowels = ['a', 'e', 'i', 'o', 'u']
    final_output = list(word)
    for letter in final_output[:]:  # iterate on copy
        if letter.lower() in vowels:
            final_output.remove(letter)

    # unintend so it only runs once after for loop completes
    word = "".join(final_output)
    return word
Abdulkadir Kollere
Abdulkadir Kollere
1,723 Points

I see!! if you lowercase while comparing, that will not change the value that was given in the first place. Thanks alot!!

Thomas Helms
Thomas Helms
16,816 Points

Could you explain why:

for letter in final_output[:]:

works, but:

for letter in final_output:

does not?

Chris Freeman
Chris Freeman
Treehouse Moderator 68,441 Points

Sure Thomas.

Keep in mind that the for loop dynamically assigns the next value to letter in each iteration.

When using the slice notation a local copy is made to use in the for loop. Iteration over the copy protects the loop from any changes to the variable final_output.

If the slice copy is not done, then changes to final_output within the loop alters the index references of the for loop source.

Let's look at an example:

# create container
container = list(range(10))

print("without slice copy")
for item in container:
    # print each item in container
    print(item)
    if item == 5:
        # remove a 5 if it exists
        container.remove(5)

container = list(range(10))

print("with slice copy")
for item in container[:]:
    print(item)
    if item == 5:
        container.remove(5)

The output would be:

without slice copy
0
1
2
3
4
5
7
8
9
with slice copy
0
1
2
3
4
5
6
7
8
9

In the first output, the 5 is removed during the sixth loop. This effectively shifts 6 to the 6th index position where the 5 used to be. So on the seventh loop iteration, 7 is in the position 6 used to be and a 7 is printed. The 6 gets skipped.