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.

John V
  • 45
  • 1
  • 7

4 Answers4

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.

C.B.
  • 8,096
  • 5
  • 20
  • 34
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
Ashwini Chaudhary
  • 244,495
  • 58
  • 464
  • 504
  • 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). – SethMMorton Feb 26 '14 at 17:19
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'))
Community
  • 1
  • 1
Toote
  • 3,323
  • 2
  • 19
  • 25
  • 1
    -1 `strip` only removes trailing and leading characters. `s.translate(None, 'aeiou')` is an option though. – Ashwini Chaudhary Feb 26 '14 at 17:13
  • Duh, my bad. I was checking the string methods and meant to use translate instead of split but my brain messed it up. Corrected – Toote Feb 26 '14 at 17:14
0

You can filter using a list comprehension, like so:

len([letter for letter in s if letter in 'aeiou'])
njzk2
  • 38,969
  • 7
  • 69
  • 107