如何在 Kotlin 中获取 Python 的切片运算符

BPS*_*BPS 4 python kotlin

Python 有一个切片运算符,我想在 Kotlin 中使用它。

我想要 Kotlin 中的以下代码

val list = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
println(
        list[5]
)
println(
        list[2, 5].joinToString()
)
println(
        list[2, 10, 2].joinToString()
)
val mutableList = mutableListOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
mutableList[2, 10, 2] = listOf(1, 2, 3, 4)
println(
        mutableList.joinToString()
)
Run Code Online (Sandbox Code Playgroud)

输出以下内容:

6
3, 4, 5
3, 5, 7, 9
1, 2, 1, 4, 2, 6, 3, 8, 4, 10
Run Code Online (Sandbox Code Playgroud)

但这不起作用!

BPS*_*BPS 6

这可以使用扩展函数和运算符重载来完成。以下代码将解决您提供的问题。经过一些调整,它也可以处理 Python 提供的所有其他选项。

operator fun <T : Any> Iterable<T>.get(start: Int, end: Int, step: Int = 1): Iterable<T> {
    check(start < end)
    check(step > 0)
    val iterator = iterator()
    var s = 0
    return generateSequence {
        while (s < start && iterator.hasNext()) {
            iterator.next()
            s++
        }
        if (iterator.hasNext()) {
            if (s < end) {
                val value = iterator.next()
                repeat(step - 1) { s++; if (iterator.hasNext()) iterator.next() }
                s++
                value
            } else {
                null
            }
        } else {
            null
        }
    }.asIterable<T>()
}

operator fun <T : Any> MutableList<T>.set(start: Int, end: Int, step: Int = 1, newElts: Iterable<T>) {
    check(start < end)
    check(step > 0)
    val iterator = iterator()
    val newIterator = newElts.iterator()
    var s = 0
    while (s < start && iterator.hasNext()) {
        iterator.next()
        s++
    }
    while (iterator.hasNext()) {
        if (s < end) {
            if (newIterator.hasNext()) {
                this[s] = newIterator.next()
                iterator.next()
                repeat(step - 1) {
                    s++;
                    if (iterator.hasNext())
                        iterator.next()
                    else
                        return
                }
                s++
            } else
                return
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

很高兴reddit上提出了另一个不使用 Python 语法的解决方案,但我很喜欢。

operator fun <T: Any> Iterable<T>.get(range: IntProgression) = asSequence().run {
    range.mapNotNull { index -> elementAtOrNull(index) }
}

operator fun <T: Any> MutableList<T>.set(range: ClosedRange<Int>, from: Iterable<T>) {
    for (i in range.start..minOf(range.endInclusive, size - 1)) removeAt(range.start)
    addAll(range.start, from.toList())
}

@Test
fun slice() {
    val list = mutableListOf(5, 6, 7, 8, 9, 10)
    assertEquals(listOf(7, 8, 9), list[2..4])
    assertEquals(listOf(10, 8), list[5 downTo 2 step 2])

    list[2..4] = listOf(77)
    assertEquals(listOf(5, 6, 77, 10), list)

    list[0..10] = listOf(1, 2, 3)
    assertEquals(listOf(1, 2, 3), list)
}
Run Code Online (Sandbox Code Playgroud)

  • @s1m0nw1 回答你自己的问题就可以了,请参阅:[我可以回答我自己的问题吗?](https://stackoverflow.com/help/self-answer) (6认同)
  • 你在回答你自己的问题吗? (5认同)