Reputation: 1668
I am trying to count vowel groups in a sentence.
My first attempt was to use list comprehension to reduce the sentence to a list of boolean values for each Char, depending on if it is a vowel or not. However, I'm not sure how to count the groups of consecutive "True" values in the list. Is there any trick to do this?
It was located in my textbook in a chapter dealing with lists and list comprehension, so I feel it has something to do with that.
Upvotes: 1
Views: 1745
Reputation: 139930
Notice that you can count the vowel groups by looking at pairs of adjacent characters. Whenever you have a consonant followed by a vowel, you've found the start of a vowel group. The exception is when the string begins with a vowel, but that can be fixed by adding a dummy consonant to the front.
To look at adjacent pairs, you can use the common trick of zipping a list with its tail, so you can get the pairs like this:
> let xs = "upheaval"
> zip ('x':xs) xs
[('x','u'),('u','p'),('p','h'),('h','e'),('e','a'),('a','v'),('v','a'),('a','l')]
All you need to do now is count the number of pairs where the first letter is a consonant and the second is a vowel. You can for example do this using a list comprehension or filter
, plus the length
function.
Upvotes: 4
Reputation: 9447
Since I don't know whether it's a homework, I'm going to give you hints:
In Data.List:
group :: Eq a => [a] -> [[a]]
-- also interesting: groupBy :: (a -> a -> Bool) -> [a] -> [[a]]
-- for example:
-- group [True, True, False, False, False, True] =
-- [[True, True], [False, False, False], [True]]
You can write your own:
isVowel :: Char -> Bool
So you should be able to get the list you mention, with Bool
s, and now you want to count the groups that are "all True".
and :: [Bool] -> Bool
or :: [Bool] -> Bool
Any of these two fellows should prove useful, since both can reduce a list of all-equal boolean values into a single value equal to them.
(EDIT: As mentioned in a comment, I'm overworking here, you just need to take the head
of each "group". In fact, you can also guess the number of vowel groups just by looking at whether the first group is a vowel/consonant, and by counting the number of groups, since for sure there is an alternation vowel/consonant!)
And now, you just need to count the True
s in this final list, since each True
represents a group of vowels!
filter :: (a -> Bool) -> [a] -> [a]
length :: [a] -> Int
You should be able to do the plumbing by yourself with these indications!
Upvotes: 5
Reputation: 183978
The Data.List
module provides the handy groupBy
function,
groupBy :: (a -> a -> Bool) -> [a] -> [[a]]
With that you can split the string into groups of consecutive vowels and non-vowels. There is no easy way using only list comprehensions, as far as I can see.
Upvotes: 2