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

标签 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

但它不起作用!

最佳答案

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

gladedreddit提出了另一种不使用 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)
}

关于python - 如何在 Kotlin 中获取 Python 的切片运算符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45947017/

相关文章:

python - 将公式应用于 pandas 行/回归线

python - Pandas :按行计算值

python - 在正则表达式匹配后获取部分数据以替换原始字符串

java - Realm 返回陈旧数据

java - 从 Java 访问 Kotlin 扩展函数

android - RecyclerView 添加了一个 "empty"布局项,当我单击它时,应用程序崩溃了

java - 在 Kotlin 中开发的 Android 库模块导出到 Java 应用程序导致 : Lkotlin/jvm/internal/Intrinsics 解析失败

python - 查找表示为列表的边

python - 如何根据字典值重命名样本

java - 如何使用 gradle 启动交互式 Java 应用程序