user12809245
user12809245

Reputation:

Counting the number of unique vowels in a string

I have the following task:

Import the sys module and create a function with a string parameter that will print the number of unique vowels in the string regardless of whether it is uppercase or lowercase.

For example:

Test 1: The argument swEet should print 1
Test 2: The argument “Aaa aeeE” should print 2
Test 3: The argument "eiOuayOI j_#Ra" should print 5

I have the following code:

import sys

def count_vowels(args):
    vowels = set()

    for arg in args:
        for char in arg:
            if char.lower() in 'aeiou':
                vowels.add(char)
    return len(vowels)

print(count_vowels(sys.argv[1:]))

Test case 1 is the only test that prints the expected output. The other two test cases, Test 2 and Test 3, do not print the correct expected result. Test 2 prints 5 rather the expected output of 4 and Test 3 prints 6 instead of the expected output of 5.

Upvotes: 1

Views: 4597

Answers (5)

Yob Haakman
Yob Haakman

Reputation: 1

You should also transform the char you append to the vowels set() to .lower(), since now it's adding the vowel as is, so the set can contain both o and O:

vowels.add(char.lower())

Upvotes: 0

Ronan Howard
Ronan Howard

Reputation: 98

The other answers and comments explain the problem well, you should use a variable to count the occurrences of each vowel. Here's a short solution using list comprehension instead of a for loop:

def count_vowels(args: str):
    args = set(args.lower())
    return sum([vowel in args for vowel in 'aeiou'])

You can even go as far as to make it a lambda function:

count_vowels = lambda args: sum([vowel in set(args.lower()) for vowel in 'aeiou'])

Upvotes: 0

Patrick Artner
Patrick Artner

Reputation: 51683

You are still mixing upper/lower casing, see other answers.

There is a lot shorter version for this

def count_vowels(word):
    # all letters you are interested in 
    allowed = frozenset("aeiou")
    # get the len of the intersection between allowed and lower cased word
    return len(allowed.intersection( word.lower()))

tests = [("swEet",1), ("Aaa aeeE", 2),("eiOuayOI j_#Ra", 5)]

for t in tests:
    print(t[0], "is", count_vowels(t[0]), "should be", t[1])

Output:

swEet is 1 should be 1
Aaa aeeE is 2 should be 2
eiOuayOI j_#Ra is 5 should be 5

This uses (frozen)set.intersection - and returns its length. frozenset is just a non-mutable version of set.

Upvotes: 1

BrokenBenchmark
BrokenBenchmark

Reputation: 19252

I think you're overcomplicating things. To get the number of unique vowels, you can lowercase the entire string, then call set() on the lowercased string to get a set of unique letters. You can then check whether each vowel is in this set. If it is, it appears in the text, otherwise it doesn't:

def count_vowels(text):
    letters = set(text.lower())
    
    count = 0
    for vowel in 'aeiou':
        if vowel in letters:
            count += 1
    return count

print(count_vowels("Aaa aeeE")) # Prints 2
print(count_vowels("eiOuayOI j_#Ra")) # Prints 5

If you prefer a one-liner, you can do this:

def count_vowels(text):
    return sum(1 for vowel in 'aeiou' if vowel in set(text.lower()))

or this (as suggested by psmears):

def count_vowels(text):
    return len(set(text.lower()) & set('aeiou'))

Upvotes: 6

rstr1112
rstr1112

Reputation: 428

Change vowels.add(char) to vowels.add(char.lower())

Upvotes: 0

Related Questions