假设我正在尝试实现一些功能:

private fun List<Int>.padWithIndices(newLength: Int): List<Int>

它获取一个列表并返回带有一些附加值的列表,其中对于每个新值,this [i] = i。

Kotlin为我们提供了很多不错的方法来附加到列表,连接两个不同的列表,创建可变列表等。如此之多,我不知道在这种情况下哪个是最好的,而且我不知道是否有任何方法隐藏的陷阱。这是我最初的基于for的解决方案,是否有更有效/惯用的解决方案?
fun List<Int>.padWithIndices(newLength: Int): List<Int> {
    var newList = this
    for (x in size until newLength) {
        newList += x
    }
    return newList
}

最佳答案

尽管您的解决方案可读性强,但它会在List<Int> -loop的每次迭代中复制原始for的所有项目,因为+=上的var newList: List<Int>每次都会创建一个新列表。最坏情况的计算复杂度为O(n²),可以提高到O(n)。

对于这种特殊情况,当您只想将连续范围添加到列表中时,像这样的单行函数将起作用:

fun List<Int>.padWithIndices(newLength: Int): List<Int> =
    plus(size until newLength)

(runnable sample)

它在接收者列表上调用 plus 函数,生成一个新列表,其中附加了参数中的项目。

您也可以将plus称为operator + ,将其替换为this + (size until newLength)

对于使用更复杂的逻辑来计算要添加到列表的项目的用例,可以使用 List(n) { ... } factory function,它接受提供列表项的lambda,从而确保每个列表项仅被计算一次:
fun List<Int>.padWithIndices(newLength: Int): List<Int> =
    List(newLength) { index -> getOrNull(index) ?: index }

(runnable sample)

函数 getOrNull(index) 返回指定索引处的项目;如果索引超出范围,则返回null。后者由?: index处理。

或者,重写您的解决方案,并在函数实现中使用可变列表,在其中添加各项,然后将其作为只读List<Int>返回:
fun List<Int>.padWithIndices(newLength: Int): List<Int> =
    toMutableList().apply {
        addAll(size until newLength)
    }

(runnable sample)

关于kotlin - Kotlin中惯用的方式来转换/附加到列表?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/56758351/

10-10 20:08
查看更多