1. Overview

Counting the number of vowels and consonants in a sentence can find useful purposes in applications from different domains, such as language learning, word games, cryptography, and so on.

In this tutorial, we’ll learn different ways to count the number of vowels and consonants in a sentence in Kotlin.

2. Using Loop

In this section, we’ll use a for loop to iterate over the string and count the number of vowels and consonants.

2.1. With if Condition

First, let’s define the VOWELS string containing both uppercase and lowercase vowel characters:

val VOWELS = "aAeEiIoOuU"

Next, we’ll write the countUsingLoopAndIfCondition() function that returns a Pair<Int, Int> having the count of vowels and consonants, respectively:

fun countUsingLoopAndIfCondition(sentence: String): Pair<Int, Int> {
    var vowelCount = 0
    var consonantCount = 0

    for (char in sentence) {
        if (char.isLetter()) {
            if (char in VOWELS) {
                vowelCount++
            } else {
                consonantCount++
            }
        }
    }
    return vowelCount to consonantCount
}

Within the for loop, we used the if condition to check and increment the vowelCount and consonantCount values accordingly.

Now, let’s define the sentence variable that contains multiple vowel and consonant characters:

val sentence: String = "alpha beta gamma delta omega Tau Upsilon"

We’ll reuse this sentence for testing all the approaches.

Finally, let’s verify that our function is working as expected:

val (vowelCount, consonantCount) = countUsingLoopAndIfCondition(sentence)
assertEquals(16, vowelCount)
assertEquals(18, consonantCount)

2.2. With when Expression

Alternatively, we can use the when expressions for condition check and incrementing the count. Let’s write the countUsingLoopAndWhenExpression() function using this approach:

fun countUsingLoopAndWhenExpression(sentence: String): Pair<Int, Int> {
    var vowelCount = 0
    var consonantCount = 0

    for (char in sentence) {
        when {
            char.isLetter() && char in VOWELS -> vowelCount++
            char.isLetter() && char !in VOWELS -> consonantCount++
        }
    }
    return vowelCount to consonantCount
}

Like earlier, let’s validate our approach:

val (vowelCount, consonantCount) = countUsingLoopAndWhenExpression(sentence)
assertEquals(16, vowelCount)
assertEquals(18, consonantCount)

3. Using Higher Order Function

We can pass a lambda as an argument to write the countUsingHigherOrderFunction() function:

fun countUsingHigherOrderFunction(sentence: String, condition: (Char) -> Boolean): Int {
    return sentence.count(condition)
}

Our higher-order function expects the caller to define the condition, and it returns the count of matching characters using the count() function.

Let’s pass lambda expressions while calling countUsingHigherOrderFunction() to determine the vowelCount and consonantCount values:

val vowelCount: Int = countUsingHigherOrderFunction(sentence, { it in VOWELS })
val consonantCount: Int = countUsingHigherOrderFunction(sentence, { it.isLetter() && it !in VOWELS })

Further, let’s verify the results:

assertEquals(16, vowelCount)
assertEquals(18, consonantCount)

4. Using Regular Expression

We can use the findAll() function from the Regex class to match characters from sentence with regex for vowels and letters:

fun countUsingRegex(sentence: String): Pair<Int, Int> {
    val vowelCount = Regex("[$VOWELS]").findAll(sentence).count()
    val consonantCount = Regex("[a-zA-Z]").findAll(sentence).count() - vowelCount
    return vowelCount to consonantCount
}

We must note that for computing consonantCount, we counted all possible letters and subtracted vowelCount.

Let’s test the countUsingRegex() function:

val (vowelCount, consonantCount) = countUsingRegex(sentence)
assertEquals(16, vowelCount)
assertEquals(18, consonantCount)

5. Using filter()

Let’s write the countUsingFilter() function using the filter() function available in the Kotlin standard library:

fun countUsingFilter(sentence: String): Pair<Int, Int> {
    val filteredChars = sentence.filter { it.isLetter() }
    val vowelCount = filteredChars.count { it in VOWELS }
    val consonantCount = filteredChars.count() - vowelCount

    return vowelCount to consonantCount
}

We extracted the letters into filteredChars and used them to count the number of vowels and consonants.

Like always, let’s confirm that our function is giving the right results:

val (vowelCount, consonantCount) = countUsingFilter(sentence)
assertEquals(16, vowelCount)
assertEquals(18, consonantCount)

6. Using Map

Another approach is to create a Map by grouping the characters from sentence by their count:

fun countUsingMap(sentence: String): Pair<Int, Int> {
    val letterCounts = sentence.groupingBy { it }.eachCount()
    val vowelCount = letterCounts.filterKeys { it in VOWELS }.values.sum()
    val consonantCount = letterCounts.filterKeys { it.isLetter() && it !in VOWELS }.values.sum()

    return vowelCount to consonantCount
}

To compute vowelCount, we filtered the VOWELS keys and aggregated the values using the sum() function. Similarly, we negated the condition for keys to be a vowel for finding consonantCount.

Now, let’s confirm that the countUsingMap() function is working as expected:

val (vowelCount, consonantCount) = countUsingMap(sentence)
assertEquals(16, vowelCount)
assertEquals(18, consonantCount)

7. Using fold()

Using the fold() extension function, we can calculate the count of vowels and consonants in the sentence. Let’s write the logic in the countUsingFold() function:

fun countUsingFold(sentence: String): Pair<Int, Int> {
    val (vowelCount, consonantCount) = sentence.fold(0 to 0) { acc, char ->
        if (char.isLetter()) {
            if (char in VOWELS) {
                acc.first + 1 to acc.second
            } else {
                acc.first to acc.second + 1
            }
        } else {
            acc
        }
    }
    return vowelCount to consonantCount
}

We use (0,0) as the initial pair value and chang the first or second member of the pair based on whether the character is a vowel or consonant. For characters that aren’t English alphabets, we return the same accumulator pair (acc).

Finally, we should test our method:

val (vowelCount, consonantCount) = countUsingFold(sentence)
assertEquals(16, vowelCount)
assertEquals(18, consonantCount)

Perfect! It looks like we nailed this one.

8. Conclusion

In this article, we learned how to count the number of vowels and consonants in Kotlin. Furthermore, we explored the loop, regular expression, fold() and filter() functions, Map data structure, and higher-order functions to solve the use case.

As always, the code from this article is available over on GitHub.