1. 概述

统计一个句子中元音(vowels)和辅音(consonants)字符的数量在多个领域都有实际应用,比如语言学习、文字游戏、密码学等。

在本教程中,我们将通过 Kotlin 编程语言,学习几种实现该功能的常用方式。每种方式都有其适用场景,我们也会结合代码示例进行说明。

2. 使用循环

使用 for 循环遍历字符串是最直观的做法。我们可以通过判断每个字符是否为字母、是否为元音来分别统计元音和辅音的数量。

2.1 使用 if 判断

首先定义一个包含大小写元音字符的字符串:

val VOWELS = "aAeEiIoOuU"

接着编写统计函数:

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
}

优点:逻辑清晰,适合初学者理解
⚠️ 缺点:写法略显冗长

测试用例如下:

val sentence = "alpha beta gamma delta omega Tau Upsilon"
val (vowelCount, consonantCount) = countUsingLoopAndIfCondition(sentence)
assertEquals(16, vowelCount)
assertEquals(18, consonantCount)

2.2 使用 when 表达式

使用 when 可以使条件判断更简洁,适用于逻辑分支较多的情况:

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
}

优点:结构更清晰,适合多条件判断
⚠️ 注意:不要遗漏 char.isLetter() 的判断,否则空格、数字等会被错误计入辅音

同样,使用上面的测试用例进行验证即可。

3. 使用高阶函数

Kotlin 的标准库提供了强大的高阶函数支持,我们可以利用这一点来封装统计逻辑。

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

调用时传入不同的判断逻辑:

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

优点:复用性强,逻辑解耦
缺点:需要对高阶函数有一定理解

4. 使用正则表达式

Kotlin 支持正则表达式操作,我们可以通过 Regex.findAll() 来匹配字符:

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
}

优点:一行代码搞定,逻辑简洁
⚠️ 注意:辅音数量是通过总字母数减去元音数得到的

测试逻辑不变,仍使用 assertEquals 验证结果。

5. 使用 filter()

使用 filter() 可以先筛选出字母字符,再进一步统计元音和辅音数量:

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
}

优点:逻辑清晰,易于测试中间结果
缺点:遍历了两次字符列表,效率略低

6. 使用 Map

我们可以将字符分组统计,然后通过 Map 来汇总元音和辅音的数量:

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
}

优点:适合需要统计每个字符出现次数的场景
⚠️ 注意:要对 MapgroupingBy 有一定了解

7. 使用 fold()

使用 fold() 可以在一个遍历中完成元音和辅音的计数,非常高效:

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
}

优点:性能好,逻辑紧凑
缺点:对不熟悉函数式编程的开发者可能不够直观

8. 总结

我们介绍了多种在 Kotlin 中统计句子中元音和辅音数量的方式,包括:

方法 特点
for + if 逻辑清晰,适合初学者
for + when 条件判断更清晰
高阶函数 复用性强,适合封装
正则表达式 简洁高效
filter() 分步处理,适合调试
Map 适合字符频率统计
fold() 单次遍历,性能好

你可以根据具体场景选择最合适的方式。例如:

  • 如果你追求简洁性,推荐使用正则或 fold()
  • 如果你需要中间结果,可以使用 filter()Map
  • 如果是教学或入门场景,推荐 for + ifwhen

完整代码可在 GitHub 上找到。


原始标题:Count the Number of Vowels and Consonants in a Sentence in Kotlin