首页 > 解决方案 > 惯用的 Kotlin 方法从标准输入求和数字直到满足条件

问题描述

我正在寻找一种惯用的方法来做到这一点,避免可变变量和循环:

fun sumOfBigDecimals() : BigDecimal{
    var sum = BigDecimal.ZERO
    while(true){
        when(val num = readBigDecimal()){
            null -> return sum
            else -> sum += num
        }
    }
}

fun readBigDecimal() = readLine()?.let { if(it.isNotEmpty()) BigDecimal(it) else null }

也欢迎任何其他使代码更简洁和可读的建议!

标签: kotlin

解决方案


您的第一个函数很好,但它是用命令式编写的。这是功能样式可以更加简洁的情况之一:

fun sumOfBigDecimals()
    = generateSequence(::readBigDecimal).reduce{ a, b -> a + b }

希望这是不言自明的,但以防万一:

库函数generateSequence构建一个序列(一个惰性列表),为每个新元素调用给定的函数,当它返回时停止null

没有sum我们可以使用的通用方法。(sumBy()假设每个值都适合Int,因此它不支持 的任意精度BigDecimal。)但是我们可以使用函数轻松构建它reduce(),将连续值相加直到只剩下一个。

一个轻微的变化是:

    = generateSequence(::readBigDecimal).reduce(BigDecimal::plus)

这使用对现有BigDecimal.plus()方法的引用来进行添加,而不是使用 lambda。它需要更多字符,但可能效率更高,您可能(或可能不会!)认为它在概念上更简单。

(您的readBigDecimal()函数肯定使用了 Kotlin 习语;它有点复杂,但我无法立即看到任何改进。)


推荐阅读