You could do something like this:
extension CharacterSet {
static let vowels: CharacterSet = CharacterSet(charactersIn: "aeiou")
static let consonants = CharacterSet.letters.subtracting(.vowels)
}
func findVowelsConsonantsPunctuation(_ sentence: String) -> (vowels: Int, consonants: Int, punctuation: Int) {
//Let's ignore diacritics
let str = sentence.folding(options: .diacriticInsensitive, locale: .current)
//The counters
var vowels = 0, consonants = 0, punctuation = 0
for character in str {
let charSet = CharacterSet(charactersIn: String(character))
//Consonants
if CharacterSet.consonants.isSuperset(of: charSet) {
consonants += 1
}
//Vowels
else if CharacterSet.vowels.isSuperset(of: charSet) {
vowels += 1
}
//Anything other than letters is considered as punctuation
else {
punctuation += 1
}
}
return (vowels, consonants, punctuation)
}
Here are some examples:
findVowelsConsonantsPunctuation("Hellö world! ") //(vowels 3, consonants 7, punctuation 4)
findVowelsConsonantsPunctuation("H311o") //(vowels 1, consonants 1, punctuation 3)
A Swift way of writing the above function would be:
func findVowelsConsonantsPunctuation(_ sentence: String) -> (consonants: Int, vowels: Int, punctuation: Int) {
let str = sentence.folding(options: .diacriticInsensitive, locale: .current)
return str.reduce((0, 0, 0)) { tuple, character in
let charSet = CharacterSet(charactersIn: String(character))
if CharacterSet.consonants.isSuperset(of: charSet) {
return (tuple.0 + 1, tuple.1, tuple.2)
}
else if CharacterSet.vowels.isSuperset(of: charSet) {
return (tuple.0, tuple.1 + 1, tuple.2)
}
else {
return (tuple.0, tuple.1, tuple.2 + 1)
}
}
}
I've switched the order of vowels and consonants in the return value since it is more probable to find a consonant than a vowel, which means the first if condition will be true more often than the others.