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

时间:2017-08-29 19:31:52

标签: 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()
)

输出以下内容:

6
3, 4, 5
3, 5, 7, 9
1, 2, 1, 4, 2, 6, 3, 8, 4, 10

但它不起作用!

1 个答案:

答案 0 :(得分:2)

这可以使用扩展函数和运算符重载来完成。以下代码将解决您提供的问题。通过一些调整,它将处理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
        }
    }
}
gladed上的{p> 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)
}