Skip to content

Instantly share code, notes, and snippets.

@geoand geoand/Kotlin List.collate
Last active Feb 12, 2017

Embed
What would you like to do?
fun <T> List<T>.collate(size: Int, step: Int = size): List<List<T>> {
require(size >= 0) {"size must not be negative"}
require(step <= size) {"step must be at most equal to size"}
return collateRec(this, size, step, listOf())
}
private tailrec fun <T> collateRec(list : List<T>, size: Int, step: Int, accumulator: List<List<T>>) : List<List<T>> {
if(list.isEmpty()) {
return accumulator
}
if(list.size < size) {
return accumulator + listOf(list)
}
return collateRec(list.subList(step, list.size), size, step, accumulator + listOf((list.subList(0, size))))
}
//Spec code
import org.assertj.core.api.Assertions.assertThat
import org.assertj.core.api.Assertions.assertThatExceptionOfType
import org.jetbrains.spek.api.Spek
class ListCollateSpec : Spek({
fun assertAppropriateExceptionThrown(block: () -> Unit) {
assertThatExceptionOfType(IllegalArgumentException::class.java).isThrownBy(block)
}
describe("List.collate invalid arguments") {
val list = (1..12).toList()
it("should throw exception because size is negative") {
assertAppropriateExceptionThrown { list.collate(-1, 2) }
}
it("should throw exception because step is larger than size") {
assertAppropriateExceptionThrown { list.collate(1, 2) }
}
it("should throw exception because step is again larger than size") {
assertAppropriateExceptionThrown { list.collate(10, 11)}
}
}
describe("List.collate no step cases") {
val list = (1..12).toList()
it("should return 12 parts of size 1 with no common elements") {
val collatedList = list.collate(1)
assertThat(collatedList).containsExactly(listOf(1), listOf(2), listOf(3), listOf(4), listOf(5), listOf(6), listOf(7), listOf(8), listOf(9), listOf(10), listOf(11), listOf(12))
}
it("should return 6 parts of size 2 with no common elements") {
val collatedList = list.collate(2)
assertThat(collatedList).containsExactly(listOf(1, 2), listOf(3, 4), listOf(5, 6), listOf(7, 8), listOf(9, 10), listOf(11, 12))
}
it("should return 4 parts of size 3 with no common elements") {
val collatedList = list.collate(3)
assertThat(collatedList).containsExactly(listOf(1, 2, 3), listOf(4, 5, 6), listOf(7, 8, 9), listOf(10, 11, 12))
}
it("should return 3 parts of size 4 with no common elements") {
val collatedList = list.collate(4)
assertThat(collatedList).containsExactly(listOf(1, 2, 3, 4), listOf(5, 6, 7, 8), listOf(9, 10, 11, 12))
}
it("should return 2 parts of size 6 with no common elements") {
val collatedList = list.collate(6)
assertThat(collatedList).containsExactly(listOf(1, 2, 3, 4, 5, 6), listOf(7, 8, 9, 10, 11, 12))
}
it("should return 1 part of size 12 with no common elements") {
val collatedList = list.collate(12)
assertThat(collatedList).containsExactly((1..12).toList())
}
it("should return a list where the last item is smaller") {
val collatedList = (1..8).toList().collate(3)
assertThat(collatedList).containsExactly(listOf(1, 2, 3), listOf(4, 5, 6), listOf(7, 8))
}
}
describe("List.collate with step cases") {
val list = (1..12).toList()
it("should return 11 parts of size 2 and a final part of size 1 containing the last element") {
val collatedList = list.collate(2, 1)
assertThat(collatedList).containsExactly(
listOf(1, 2), listOf(2, 3), listOf(3, 4), listOf(4, 5), listOf(5, 6), listOf(6, 7),
listOf(7, 8), listOf(8, 9), listOf(9, 10), listOf(10, 11), listOf(11, 12), listOf(12)
)
}
it("should return 3 parts of size 6 and a final part of size 3") {
val collatedList = list.collate(6, 3)
assertThat(collatedList).containsExactly(listOf(1, 2, 3, 4, 5, 6), listOf(4, 5, 6, 7, 8, 9), listOf(7, 8, 9, 10, 11, 12), listOf(10, 11, 12))
}
it("should return on part of size 7 and one of size 6") {
val collatedList = list.collate(7, 6)
assertThat(collatedList).containsExactly(listOf(1, 2, 3, 4, 5, 6, 7), listOf(7, 8, 9, 10, 11, 12))
}
}
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.