8. Making my code nicer


#1

I wrote this for lesson 8 (anti_vowel), and it works, but it seems kind of inefficient (going through every vowel for every letter). Is that basically the best it can be done?

vowels = "aeiouAEIOU"

def anti_vowel(text):
    new_word = ""
    for letter in text:
        remove = False
        for vowel in vowels:
            if letter == vowel:
                remove = True
                break
        if remove == False:
            new_word = new_word + letter
    return new_word

#2

We are discussing simplicity in the matter of the computational complexity or in the matter of how the code looks? We are discussing the general problem of deleting a specified characters from the string or we are talking only about this, particular usage?


If we are talking about computational complexity and about the general problem answer is -> yes, we can do it better. Now you have a O(nk) complexity, where n is the length of text and k is the length of vowels.

There are two better solutions that come to my mind:

  • you can turn vowels into set and check with the in operation if given letter should be deleted | average complexity is O(n)
  • you can turn vowels into the list which will be indexed by ASCII codes and will hold boolean values (true - letter should be deleted) | complexity of this solution is O(n), but we need to use extra space

If we are talking about this particular problem:

vowels = "aeiouAEIOU"

def anti_vowel(text):
    return ''.join([letter for letter in text if letter not in vowels])

print anti_vowel("Lorem Ipsum Dolor Sit Amet")

This code is based upon a simple for loop and in operation to check whether given letter is a vowel or not.


#3

Could you possibly explain this:

return ''.join([letter for letter in text if letter not in vowels])


#4

Actually, I think I understand it now. I hadn't seen that format before, but I've arrived at the lesson that uses that format. Didn't know about the "not in" though.