Last active
April 11, 2018 15:24
-
-
Save venkatperi/57c8a20d7a81325b50dc6b1e9d5c7de5 to your computer and use it in GitHub Desktop.
Kotlin: Split Iterable into two at given index
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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)) | |
} | |
} | |
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* 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