How can I get Python's slice operator in Kotlin

Answer #1 100 %

This can be accomplished using extension functions and operator overloading. The following code will solve the problem you provide. With some adjustment, it would handle all the other options that Python provides as well.

operator fun  Iterable.get(start: Int, end: Int, step: Int = 1): Iterable {
    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()
}

operator fun  MutableList.set(start: Int, end: Int, step: Int = 1, newElts: Iterable) {
    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 on reddit came up with another solution that doesn't use Python's syntax but I quite like.

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

operator fun  MutableList.set(range: ClosedRange, from: Iterable) {
    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)
}

You’ll also like:


© 2023 CodeForDev.com -