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)
}