Skip to content

Instantly share code, notes, and snippets.

@iseki0
Created February 13, 2020 08:17
Show Gist options
  • Save iseki0/950645ff61ea9e1d9705a59c1cef9aec to your computer and use it in GitHub Desktop.
Save iseki0/950645ff61ea9e1d9705a59c1cef9aec to your computer and use it in GitHub Desktop.
kotlin slice with default and negative index
internal fun <T> List<T>.slice(indices: Iterable<Int>, default: (index: Int) -> T): List<T> {
fun measureSizeOrDefault(iterator: Iterable<Int>, defaultValue: Int): Int =
when (iterator) {
is IntProgression -> {
iterator.run {
when {
step > 0 -> if (first > last) 0 else ((last - first) / step) + 1
step < 0 -> if (last > first) 0 else ((first - last) / step.absoluteValue) + 1
else -> error("step equals zero.")
}
}
}
is Collection<Int> -> iterator.size
else -> defaultValue
}
val size = measureSizeOrDefault(indices, 10)
val target = ArrayList<T>(size)
val availRange = 0..this.lastIndex
indices.forEach {
val pos = if (it < 0) this.size + it else it
if (pos in availRange) {
target.add(this[pos])
} else {
target.add(default.invoke(pos))
}
}
return target
}
internal class UtilKtTest {
@Test
fun slice() {
val list = listOf(0, 1, 2, 3, 4, 5, 6, 7, 8)
assertEquals(list.slice(1..5) { 0 }, listOf(1, 2, 3, 4, 5))
assertEquals(list.slice(0..1) { 0 }, listOf(0, 1))
assertEquals(list.slice(1..0) { 0 }, emptyList<Int>())
assertEquals(list.slice(1..1) { 0 }, listOf(1))
assertEquals(list.slice(0..0) { 0 }, listOf(0))
assertEquals(list.slice(0..20) { it }, (0..20).toList())
assertEquals(list.slice(-5..-1) { 0 }, listOf(4, 5, 6, 7, 8))
assertEquals(list.slice(-5..1) { 0 }, listOf(4, 5, 6, 7, 8, 0, 1))
assertEquals(list.slice(0..5 step 2){0}, listOf(0,2,4))
assertEquals(list.slice(0..6 step 2){0}, listOf(0,2,4,6))
assertEquals(list.slice(5 downTo 0){0}, listOf(5,4,3,2,1,0))
assertEquals(list.slice(3 downTo -3){0}, listOf(3,2,1,0,8,7,6))
assertEquals(list.slice(3 downTo -3 step 2){0}, listOf(3,1,8,6))
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment