Skip to content

Instantly share code, notes, and snippets.

@iseki0
Last active February 13, 2020 09:07
Show Gist options
  • Save iseki0/394e336c90b3e708f384acd3132a4d11 to your computer and use it in GitHub Desktop.
Save iseki0/394e336c90b3e708f384acd3132a4d11 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> {
val size = indices.measureSizeOrDefault(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 fun Iterable<Int>.measureSizeOrDefault(defaultValue: Int): Int =
when (this) {
is IntProgression -> {
this.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> -> this.size
else -> defaultValue
}
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(listOf(0, 0, 0, 0, 1, 2, 3), listOf(1, 2, 3).slice(-7..-1) { 0 })
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))
}
@Test
fun measureSizeOrDefault() {
assertEquals(5, (1..5).measureSizeOrDefault(10))
assertEquals(0, (1..0).measureSizeOrDefault(10))
assertEquals(6, (0..10 step 2).measureSizeOrDefault(10))
assertEquals(6, (10 downTo 0 step 2).measureSizeOrDefault(10))
assertEquals(3, listOf(1, 2, 3).measureSizeOrDefault(10))
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment