Skip to content

Instantly share code, notes, and snippets.

@venkatperi
Last active April 11, 2018 15:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save venkatperi/57c8a20d7a81325b50dc6b1e9d5c7de5 to your computer and use it in GitHub Desktop.
Save venkatperi/57c8a20d7a81325b50dc6b1e9d5c7de5 to your computer and use it in GitHub Desktop.
Kotlin: Split Iterable into two at given index
object IterableExtSpec : Spek({
val list = (0 until 100).toList()
describe("splitAt") {
it("asserts when n < 0") {
assertFailsWith<IllegalArgumentException> {
list.splitAt(-2)
}
}
it("returns <empty, original> when n = 0") {
assertEquals(listOf<Int>() to list, list.splitAt(0))
}
it("returns <original, empty> when n = size") {
assertEquals(list to listOf(), list.splitAt(list.size))
}
it("returns <original, empty> when n > size") {
assertEquals(list to listOf(), list.splitAt(list.size + 10))
}
it("otherwise splits the list as desired") {
assertEquals(list.take(20) to list.takeLast(list.size - 20), list.splitAt(20))
}
}
})
/**
* Splits the given `Iterable` into two at index [n].
*
* @return Pair<List<T>, List<T>>
*/
fun <T> Iterable<T>.splitAt(n: Int): Pair<List<T>, List<T>> =
when {
n < 0 ->
throw IllegalArgumentException(
"Requested split at index $n is less than zero.")
n == 0 ->
emptyList<T>() to toList()
this is Collection<T> && (n >= size) ->
toList() to emptyList()
else -> {
var idx = 0
val dn = if (this is Collection<T>) size - n else n
val left = ArrayList<T>(n)
val right = ArrayList<T>(dn)
@Suppress("UseWithIndex")
for (item in this) {
when (idx++ >= n) {
false -> left.add(item)
true -> right.add(item)
}
}
left to right
}
}.let {
it.first.optimizeReadOnlyList2() to it.second.optimizeReadOnlyList2()
}
/**
* Original function is internal in the stdlib
*/
fun <T> List<T>.optimizeReadOnlyList2(): List<T> = when (size) {
0 -> emptyList()
1 -> listOf(this[0])
else -> this
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment