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

how to remove string items from a list, or string list from list, and convert list to string

I tried to solve this exercise by first converting string to list A created list of items to remove B attempted to remove B from A (didn't work) and convert new A back to string (didn't work)

disemvowel.py
def disemvowel(word):
    wurd=list(word)
    what2remove=["A", "E", "I", "O", "U", "a", "e", "i", "o", "u"]
    for letters in wurd:
        try:
         wurd=wurd.remove(what2remove)
        except ValueError:
            pass
    word=str(wurd, ", ")
    return word

wordyburdy=disemvowel("luna")
print(wordyburdy)

1 Answer

Alex Koumparos
seal-mask
.a{fill-rule:evenodd;}techdegree
Alex Koumparos
Python Development Techdegree Student 36,887 Points

Hi Aaesha,

You have a few issues with your code. Let's start by looking at those:

First, your remove line:

wurd=wurd.remove(what2remove)

In your case, what2remove is a list. So the behaviour of this line is that Python will look to see if it can find exactly that list (i.e., the whole of ["A", "E", "I", "O", "U", "a", "e", "i", "o", "u"]) in your 'wurd' list and then remove the first instance of it that it finds. Of course, it's not going to find that list inside your list, so you'll never get a match.

There are ways to do what you are trying to do, check if any members of a list are in another list, but those techniques are best left for later, after you've become more comfortable with the fundamentals.

The simplest way to check if an item 'x' is in list 'L' in Python would be to do this:

if x in L:
    # do something
else:  # x wasn't in L
    # do something else

However, this is where you run in to a more subtle issue. When you are using a 'for in' loop to iterate through a collection, you don't want to remove items from that collection as you're going through it, because this can cause Python to skip elements.

For example, suppose we had the list ['h', 'e', 'l', 'l', 'o'] and we wanted to remove each instance of e and l from it. We might expect we could write something like this:

>>> word = ['h', 'e', 'l', 'l', 'o']
... for letter in word:
...     if letter in ['e', 'l']:
...         word.remove(letter)
...    print(f'current letter: {letter} => word is now {word}')  # let's print the letter and word at the end of each iteration to see what's happening

And then we might be surprised to find that word ends up as ['h', 'l', 'o'].

Let's look at the output and see if that gives us any clues:

current letter: h => word is now ['h', 'e', 'l', 'l', 'o']
current letter: e => word is now ['h', 'l', 'l', 'o']
current letter: l => word is now ['h', 'l', 'o']

The first two iterations are exactly what we were expecting, but surprisingly, we finish after the third iteration. This is because Python gets to the end of the third iteration and decides that since it was third iteration and the collection has a length of three (after we've removed two items), it must be finished. So we've skipped over the second l and the o.

A couple of approaches to this challenge that would avoid the problem might be:

  • instead of mutating the original list, create a copy of the list. Use the original list to iterate through but make changes to the copy; or
  • instead of removing items you don't want, build a new string from letters that you do want. You could start with an empty string and as you iterate through the original list, if the letter isn't in the list of vowels, you could add that letter to your new string.

Moving on in your code, your next major issue is in your use of str() to reconstruct the string from the list:

word=str(wurd, ", ")

In Python, the syntax for creating a string by joining the elements of a list with a specified character would be:

>>> ",".join(['a', 'b', 'c'])
'a,b,c'

However, you're not trying to join the elements with a separator character, so you can just do this:

>>> "".join(['a', 'b', 'c'])
'abc'

Now that we've handled the errors, let's see if we can simplify the code.

To begin, It's worth pointing out that for many practical purposes, strings can behave like lists. For example, you can iterate through a string just like if it was a list:

>>> for letter in 'hello':
...    print(letter)
'h'
'e'
'l'
'l'
'o'

Similarly, you can check membership of a substring in a string:

>>> if 'i' not in 'team':
...    print("There's no 'i' in 'team'")
There's no 'i' in 'team'
>>> if 'm' in 'team' and 'e' in 'team':
...    print("But there is a 'me' if you look hard enough")
But there is a 'me' if you look hard enough

This means that you can write your whole disemvowel function without ever worrying about needing to turn the string into a list and then back to a string.

Also, it's worth noting that you don't need to check for lower and upper case letters separately. Suppose you have a string like 'HeLlO'. You want to check for instances of the letter l or the letter 'i' but you don't care about case, you can do this:

>>> for letter in 'HeLlo':
...    if letter.lower() in 'li':
...        print(f'{letter} is in "HeLlO"')
L is in "HeLlO"
l is in "HeLlO"

Hope that helps,

Cheers

Alex