我如何使用优雅的kotlin技术来解决这个问题?(FP)



我有一个kotlin问题,你能想出一个优雅的方法来解决它吗?

所以实际上我有一个旅行列表,可能是开车或不开车,我想找到列表中连续有汽车旅行的地方;例如,列表中有2辆或更多的车排成一行。然后从这些连续的汽车链中,我想对每条链的里程求和,并打印出最大值。这是数据类

data class Journey(
val isCar: Boolean = false,
val mileage: Int,
)

下面是一个旅程示例列表。所以在这个例子中,正确答案应该是80,因为有两个连续的条目,40+40是里程。这打败了唯一一个连续输入的10+20=30。其余的是单车旅行和非汽车旅行,因此被忽略。

listOf(
Journey(true, 10),
Journey(true, 20),
Journey(false, 105),
Journey(true, 1046),
Journey(false, 130),
Journey(true, 40),
Journey(true, 40),
)

我的解决方案如下,但它非常丑陋和无功能。你能用一种优雅的方式解决这个问题吗?由于

val journeys = listOf(
Journey(true, 10),
Journey(true, 20),
Journey(false, 105),
Journey(true, 1046),
Journey(false, 130),
Journey(true, 40),
Journey(true, 40),
)
val cars = journeys.filter { it.isCar }
val journeysByIndex = cars.map { journeys.indexOf(it) to it  }
val consecutiveJourneys = mutableListOf<MutableList<Journey>>()
journeysByIndex.forEach {
if (consecutiveJourneys.any { cj1 -> cj1.any { cj2 -> cj2 == it.second  } }) {
return@forEach
}
val journeyList = mutableListOf(it.second)
var index = it.first
var nextJourneyExists = true
while (nextJourneyExists) {
var journey: Journey? = null
if ((index + 1) < journeys.size  && journeys[index + 1].isCar) {
journey = journeys[index+1]
}
nextJourneyExists = if (journey!= null) {
journeyList.add(journey)
true
} else {
false
}
index += 1
}
consecutiveJourneys.add(journeyList)
}
var maxAmountForConsecutive = consecutiveJourneys.filter {it.size > 1 }.map{ it.sumOf {cs -> cs.mileage}}.max()
println("max1: " + maxAmountForConsecutive)

除了Tenfour04在评论中建议的分组方法之外,我个人认为对于这样的任务有点过度(但在其他场景中很有用),您还可以简单地计数。

我们可以创建一个简单的扩展函数,计算每一步,然后在到达isCar:false时重置:

fun Collection<Journey>.calculateMaxByCarConsecutive(): Int {
var max = 0
var currentMileageSum = 0
var count = 0
forEach { current ->
if (current.isCar) {
//if the current journey is in a car, add its mileage to our current count
currentMileageSum += current.mileage
//increase count that tells us how many journeys have been consecutive
count++
//if we have more than 1 journey creating the currentMileageSum 
//and 
//currentMileageSum is greater than max, 
// then the currentMileageSum becomes the new max
if (count > 1) max = maxOf(currentMileageSum, max)
} else {
//reset the counters if this record is not by car
count = 0
currentMileageSum = 0
} 
}
return max
}

那么我们可以这样命名它:

val journeys = listOf(
Journey(true, 10),
Journey(true, 20),
Journey(true, 40),
Journey(false, 105),
Journey(true, 10423423),
Journey(false, 130),
Journey(true, 40),
Journey(true, 40),
Journey(true, 10),
)
val maxJourneyByCar = journeys.calculateMaxByCarConsecutive()
println(maxJourneyByCar) //this will print 90

不确定这是否比你的解决方案更优雅,或者比使用fold,但我确实认为它更简单。

最新更新