1

I'm trying to program something that will filter all the vowels out of a string of text and I'm not sure why my function doesn't work. Here's my code

def anti_vowel(text):
 letters = text.split() #make a list of all the letters in the string
 index = 0 #for del
 for x in letters:
     if x == "a" or x == "A" or x == "u" or x == "U" or x == "i" or x == "I" or x == "o" or x == "O" or x == "e" or x == "E":
         del letters[index]
     index += 1 #to make the if-clause work
 return "".join(letters) #turn the edited list into a string

While iterating over letters the if-clause should be activated when the object in letters is a vowel right? so it should delete that object. But what am I doing wrong?

4
  • 5
    You should not alterate a list while iterating through it. Commented Jul 14, 2015 at 17:15
  • 1
    filter Commented Jul 14, 2015 at 17:15
  • 1
    You are using del letters[index]. The list is getting smaller and smaller, and when you do index += 1 you are actually skipping over an element(which was moved because of the delete). Commented Jul 14, 2015 at 17:17
  • Related Commented Jul 14, 2015 at 17:18

5 Answers 5

5

I would use re.sub

re.sub(r'(?i)[AEIOU]', '', st)

Explanation:

  • (?i) case-insensitive modifier helps to do case insensitive match.
  • [AEIOU] matches any one charcater from the given list. Since we already added the case-insensitive modifier, this would match both upper and lowercase vowels.
Sign up to request clarification or add additional context in comments.

1 Comment

Mind adding a link to re.sub there?
4

Your code isn't iterating through letters, it's iterating through words. This is because text.split() splits your text into a list of whitespace-separated "word" strings.

The next problem is that you're iterating through a list and deleting entries. Mutating an iterable while iterating through it is a common cause of strange results.

Instead, do something like this:

def anti_vowel(text):
    return ''.join(filter(lambda x: x.lower() not in 'aeioe', text))

Result:

>>> anti_vowel('hi my name is joe')
'h my nm s j'

Comments

2

I rather Avinash's approach, but if you want to fix your impl. here's how to do it:

def anti_vowel(text):
    letters = list(text)
    i = 0
    while i < len(letters):
        x = letters[i]
        if x in "aAeEiIoOuU":
            del letters[i]
        else:
            i += 1
    return "".join(letters)

3 Comments

This doesn't work because the letters = text.split() splits the text into words that were separated by whitespace, not letters. Also, modifying what you're iterating over is generally a bad idea.
Keeping text.split(), this will only work if the string contains whitespace between each character.
if x in "aAeEiIoOuU": would be more succinct.
1

''.join(c for c in text if c.lower() not in 'aeiou')

This uses a generator expression to look at each letter in the string, and only keep it if it is not a vowel (its lowercase is not in 'aeiou'), then joins these valid characters.

Comments

1

You could use list comprehension and create something like this

def anti_vowel2(text):
    return "".join([x for x in text if x.lower() not in 'aeiou'])

print(anti_vowel2("test"))

which outputs the string tst

1 Comment

You can refactor that long predicate into simply if x.lower() not in 'aeiou'.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.