Kotlin:在某些对象的某些列表中找到最小元素的第一个索引的最有效方法

gro*_*gor 7 kotlin

我有一些自定义类的实例列表:

data class Flight(val duration: Int)
Run Code Online (Sandbox Code Playgroud)

例如:

val flights = listOf(Flight(10), Flight(5), Flight(5), Flight(15), Flight(20))
Run Code Online (Sandbox Code Playgroud)

如何最有效地找到此列表中最小元素的第一个索引?在这种情况下,min 元素的第一个索引是 1,因为航班 [1].duration = 5。

s1m*_*nw1 10

我猜这样的事情将是“最有效的”:

var min: Pair<Int, Flight>? = null
for (f in flights.withIndex()) {
    if (min == null || min.second.duration > f.value.duration) min = f.index to f.value
}
Run Code Online (Sandbox Code Playgroud)

而这个基本上是一样的,看起来好多了:

flights.withIndex().minBy { (_, f) -> f.duration }?.index
Run Code Online (Sandbox Code Playgroud)

  • 这两种方法在这方面是相同的。一旦你使用了`withIndex()`,你就会得到一系列新创建的实例,这些实例同时包含了项目和它的索引。检查 [forpas](/sf/answers/3868227121/) 的第二个解决方案,看看我用“更多代码”是什么意思来获得零垃圾解决方案。如果不允许我对输入​​的大小做任何假设,那就是我会采用的解决方案。但是一旦我可以假设少量项目和代码不涉及热循环,我就会选择更紧凑的变体。 (2认同)

for*_*pas 6

使用minBy()获取具有最短持续时间的列表项,
然后使用indexOf()获取其索引:

val index = flights.indexOf(flights.minBy { it.duration })
Run Code Online (Sandbox Code Playgroud)

对于列表的 1 次扫描,您可以执行经典循环:

var index = if (flights.isEmpty()) -1 else 0
flights.forEachIndexed { i, flight ->
    if (flight.duration < flights[index].duration) index = i
}
Run Code Online (Sandbox Code Playgroud)