You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何简化Kotlin中的when表达式?优化数字与字符分支逻辑

简化Kotlin代码中的when表达式

我希望简化这段Kotlin代码中的when表达式,尤其是char.isDigit()和char.isLetter()对应的分支逻辑,请问该如何操作?

原始处理代码

smoothInput.forEach { char ->
    when {
        char.isValidOperator() -> {
            output.push(char)
        }

        char.isDigit() -> {
            if (output.isNotEmpty() && output.last()!!.isNumeric()) output.addToLast(char)
            else output.push(char)
        }

        char.isLetter() -> {
            if (output.isNotEmpty() && output.last()!!.isValidVariableName()) output.addToLast(char)
            else output.push(char)
        }

        else -> {
            throw InvalidIdentifierException()
        }
    }
}

补充定义代码

InputStack类

class InputStack : Stack<String> {

    override val storage = mutableListOf<String>()
    fun push(e: Char) = push(e.toString())
    fun push(e: Operator) = push(e.toString())

    fun addToLast(e: Char) {
        storage[storage.size - 1] += e.toString()
    }
}

Stack接口

interface Stack<T> {
    val storage: MutableList<T>
    fun asString(): String = buildString {
        appendLine("----top----")
        storage.asReversed().forEach {
            appendLine(it)
        }
        appendLine("-----------")
    }

    fun push(element: T) = storage.add(element)
    fun pop(): T {
        if (storage.size == 0) throw EmptyStackException()
        return storage.removeAt(storage.size - 1)
    }

    fun isEmpty(): Boolean = storage.isEmpty()
    fun isNotEmpty(): Boolean = !isEmpty()
    fun last(): T? = storage.lastOrNull()
    fun forEach(action: (T) -> Unit) {
        for (element in storage) action(element)
    }
}

简化方案

观察代码可知,char.isDigit()和char.isLetter()的分支逻辑高度重复,仅判断栈顶元素的条件不同。可通过封装重复逻辑、合并分支实现简化:

1. 封装通用处理函数

抽离重复的"判断栈顶条件→选择追加/推入"逻辑为独立函数:

private fun handleChar(output: InputStack, char: Char, isValidTop: (String) -> Boolean) {
    if (output.isNotEmpty() && isValidTop(output.last()!!)) {
        output.addToLast(char)
    } else {
        output.push(char)
    }
}

2. 简化when表达式

复用上述函数,合并digit和letter分支:

smoothInput.forEach { char ->
    when {
        char.isValidOperator() -> output.push(char)
        char.isDigit() -> handleChar(output, char) { it.isNumeric() }
        char.isLetter() -> handleChar(output, char) { it.isValidVariableName() }
        else -> throw InvalidIdentifierException()
    }
}

3. 扩展性优化(可选)

若后续可能新增更多字符类型判断,可通过映射表匹配处理逻辑,提升扩展性:

val charHandlers = mapOf(
    Char::isValidOperator to { output: InputStack, char: Char -> output.push(char) },
    Char::isDigit to { output: InputStack, char: Char -> handleChar(output, char) { it.isNumeric() } },
    Char::isLetter to { output: InputStack, char: Char -> handleChar(output, char) { it.isValidVariableName() } }
)

smoothInput.forEach { char ->
    charHandlers.entries.find { it.key(char) }?.value?.invoke(output, char)
        ?: throw InvalidIdentifierException()
}

说明

  • 第一种方案保留原when表达式的可读性,同时消除重复代码,是最稳妥的选择。
  • 第二种映射方案适合需频繁扩展字符类型判断的场景,代价是可读性略有下降,可按需选用。

内容的提问来源于stack exchange,提问作者halotukozak

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 13:03:17