0

Working on a problem in which I am trying to get a count of the number of vowels in a string. I wrote the following code:

def vowel_count(s):
    count = 0
    for i in s:
        if i == 'a' or i == 'e' or i == 'i' or i == 'o' or i == 'u':
            count += 1
    print count
vowel_count(s)

While the above works, I would like to know how to do this more simply by creating a list of all vowels, then looping my If statement through that, instead of multiple boolean checks. I'm sure there's an even more elegant way to do this with import modules, but interested in this type of solution.

Relative noob...appreciate the help.

4
  • a way to do this: stackoverflow.com/questions/2926383/counting-vowels Commented Feb 26, 2014 at 17:10
  • For learning's sake, if you want to maintain your current for loop structure, change the multiple boolean checks to if i in ('a','e','i','o','u'): Commented Feb 26, 2014 at 17:13
  • @JesseMu if i in ('a', 'e', 'i', 'o', 'u'): is more appropriate, because if i in 'aeiou': will also match i == 'eio', which is not the intent of the code. Commented Feb 26, 2014 at 17:14
  • @SethMMorton Good point, edited Commented Feb 26, 2014 at 17:15

4 Answers 4

4

No need to create a list, you can use a string like 'aeiou' to do this:

>>> vowels = 'aeiou'
>>> s = 'fooBArSpaM'
>>> sum(c.lower() in vowels for c in s)
4
Sign up to request clarification or add additional context in comments.

1 Comment

For ultimate speed and clarity, I would recommend vowels = set('aeiou'). This has two advantages: 1) Internally, this becomes {'a', 'e', 'i', 'o', 'u'} which is actually the intent of the code since i in 'aeiou' could match 'eou` and that is not what the OP wants, and 2) set memberships are fast (not really an issue here because the iterable is 5 elements but it could matter for longer strings).
4

You can actually treat a string similarly to how you would a list in python (as they are both iterables), for example

vowels = 'aeiou'
sum(1 for i in s if i.lower() in vowels)

For completeness sake, others suggest vowels = set('aeiou') to allow not matching checks such as 'eio' in vowels. However note if you are iterating over your string in a for loop one character at a time, you won't run into this problem.

5 Comments

a string as a list not exactly. both strings and lists are iterables, which allow them to but iterated.
sum([i.lower() in vowels for i in s]) would also work because True == 1 in python.
@SethMMorton agreed more idiomatic. Since this is provided in Ashwini's post I'll leave as is.
The proper syntax is either set(['a','e','i','o','u']) or set('aeiou') because set must take an iterable.
@SethMMorton just fixed before your comment.
1

A weird way around this is the following:

vowels = len(s) - len(s.translate(None, 'aeiou'))

What you are doing with s.translate(None, 'aeiou') is creating a copy of the string removing all vowels. And then checking how the length differed.

Special note: the way I'm using it is even part of the official documentation

What is a vowel?

Note, though, that method presented here only replaces exactly the characters present in the second parameter of the translate string method. In particular, this means that it will not replace uppercase versions characters, let alone accented ones (like áèïôǔ).

Uppercase vowels

Solving the uppercase ones is kind of easy, just do the replacemente on a copy of the string that has been converted to lowercase:

vowels = len(s) - len(s.lower().translate(None, 'aeiou'))

Accented vowels

This one is a little bit more convoluted, but thanks to this other SO question we know the best way to do it. The resulting code would be:

from unicodedate import normalize

# translate special characters to unaccented versions
normalized_str = normalize('NFD', s).encode('ascii', 'ignore')
vowels = len(s) - len(normalized_str.lower().translate(None, 'aeiou'))

2 Comments

-1 strip only removes trailing and leading characters. s.translate(None, 'aeiou') is an option though.
Duh, my bad. I was checking the string methods and meant to use translate instead of split but my brain messed it up. Corrected
0

You can filter using a list comprehension, like so:

len([letter for letter in s if letter in 'aeiou'])

Comments

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.