Kotlin 计算所有列表元素的总和,直到满足条件为止
我面临以下问题:我有一个对象列表。让它成为类测试的对象:Kotlin 计算所有列表元素的总和,直到满足条件为止,kotlin,Kotlin,我面临以下问题:我有一个对象列表。让它成为类测试的对象: data class Test( var status: String, // Can be EXPIRED, WAIT var amount: Float ) 数组被排序后,在开始和之后都有状态为WAIT的对象,状态为EXPIRED。我需要计算状态为过期的所有元素(如果存在)的总和,并将类型为等待的第一个对象(如果存在)的总和相加。现在我有以下代码: private fun getRestructuringAmoun
data class Test(
var status: String, // Can be EXPIRED, WAIT
var amount: Float
)
数组被排序后,在开始和之后都有状态为WAIT
的对象,状态为EXPIRED
。我需要计算状态为过期的所有元素(如果存在)的总和,并将类型为等待的第一个对象(如果存在)的总和相加。现在我有以下代码:
private fun getRestructuringAmountToPay(): Float {
var i = 0
var sum = 0F
list?.forEachIndexed { iter, el ->
if (el.status != RestructingItemStatus.WAIT) {
i = iter
sum += el.amount ?: 0F
}
}
if (i + 1 < (list?.size ?: 0)) {
sum += list?.get(i+1)?.amount ?: 0F
}
return sum
}
private fun getRestructuringAmountToPay():Float{
变量i=0
var总和=0F
列表?.forachinedexed{iter,el->
if(el.status!=重构项状态。等待){
i=国际热核实验堆
总和+=el.金额?:0F
}
}
如果(i+1<(列表?.size?:0)){
总和+=列表?获取(i+1)?。金额?:0F
}
回报金额
}
但是有没有办法改进这段代码,让它变得漂亮呢?提前感谢您的帮助 我会走老路,使用for
循环,而不是forachined
方法,这样当我点击第一个等待
条目时,我就可以打破
循环。我会这样做:
private fun getRestructuringAmountToPay(): Float {
var sum = 0F
for (el in list) {
if (el.status == RestructingItemStatus.WAIT) {
el.amount += sum
break
}
else {
sum += el.amount
}
}
return sum
}
这是一种简单而优雅的方法,可以在不需要对列表进行任何额外迭代的情况下完成最少量的工作。如果你是“我必须把所有东西塞进尽可能少的代码行”中的一员,那么肯定有更复杂、更紧凑的方法可以做到这一点。我常常难以理解此类解决方案的实际优势。当您说要查找列表中状态为“EXPIRED”
的所有元素时,我想到了filter()
。当你说要求和时,我想到了sumBy()
。当您说要将该数字添加到列表中状态为“WAIT”
的第一个元素时,我想到了first()
我们实际上不能使用正常的sumBy()
函数,因为Test.amount
属于Float
类型,所以我们可以做的最接近的事情就是使用sumByDouble()
并将amount
转换为Double
val expiredSum = list.filter { it.status == "EXPIRED" }.sumByDouble { it.amount.toDouble() }
val result = list.first { it.status == "WAIT" }.amount + expiredSum
如果不希望在没有状态为“WAIT”的元素时引发异常,请改用firstOrNull()
:
val expiredSum = list.filter { it.status == "EXPIRED" }.sumByDouble { it.amount.toDouble() }
val initialValue = list.firstOrNull { it.status == "WAIT" }?.amount ?: 0F
val result = initialValue + expiredSum
我不确定我是否理解您的解决方案,但我分别理解您的目标:
var sum = list.filter { it.status == "EXPIRED" }.sumByDouble { it.amount.toDouble() }
list.firstOrNull{ it.status == "WAIT" }?.let { sum+=it.amount}
println(sum)
由于您的列表已排序,并且EXPIRED
项目位于第一位,因此您可以使用firstOrNull
要查找状态为等待的第一项,请执行以下操作
当您迭代过期的
项目时,您可以使用一个简单的变量对金额
求和,当您找到第一个等待
项目时,只需将该金额分配给金额
var sum: Float = 0f
list.firstOrNull {
sum += it.amount
it.status == "WAIT"
}?.apply {
this.amount = sum
}
事实上,你的代码并不是你想要的
计算状态为EXPIRED(如果存在)的所有元素的总和,并将类型为WAIT(如果存在)的第一个对象的数量添加到此总和中
它计算状态为过期(如果存在)的所有元素的总和,并将状态为过期(如果存在)的最后一个对象(如果存在)之后的类型为WAIT的第一个对象的金额或索引为1(如果存在)的对象的金额(如果不存在状态为过期的元素)相加:
println(GetRestructuringaMountPay(listOf(Test(“EXPIRED”,1f),Test(“WAIT”,1f),Test(“EXPIRED”,1f)))//将打印2.0,而按照原始描述,它应该是3.0
println(getRestructuringAmountToPay(listOf(Test(“WAIT”,1f),Test(“WAIT”,100f)))//将打印100.0,而按照最初的描述,它应该是1.0
要以Kotlin方式获得最初想要的行为,您需要执行以下操作:
if (list == null) return 0f //get rid of nullability
val (expired, waiting) = list.partition { it.status != "WAIT" } //split original list into respectful partitions
val sum = expired.map { it.amount }.sum() + (waiting.firstOrNull()?.amount ?: 0f) //do the calculations
Pretty是主观的——下面的代码很短,但无可否认,它没有利用集合的“排序”特性
fun sum(数据:列表):双倍{
val expiredSum=data.filter{it.status==“EXPIRED”}.sumByDouble{it.amount}
val waitSum=data.find{it.status==“WAIT”}?.amount?:0.0
返回expiredSum+waitSum
}
你说你想汇总所有状态为“等待”的项目,但似乎你做的恰恰相反。@Steve是的,对不起,更新了问题我必须同意你的意见我非常喜欢这个解决方案。它将我的老式解决方案的可读性与更现代的流媒体风格相结合。下次回到Kotlin编程时,我会把它作为模板记住。@Steve谢谢,我真的很感激!很好的解决方案!