Ruby (and other languages) has a very nice feature with arrays where you can slice them in arbitrarily large slices. I have made an extension method that does it, but it would be nicer if it was properly done by professionals
inline fun <reified T> arrayEachSlice(array: Array<T>, size: Int): Array<Array<T>?> {
val result: Array<Array<T>?> = arrayOfNulls(array.size.div(size) + 1)
for (i in 0..array.lastIndex step size) {
result[i.div(size)] = if (i == array.lastIndex) {
arrayOf(array.last())
} else
array.copyOfRange(i, if (i + size <= array.lastIndex + 1) i + size else array.lastIndex + 1)
}
return result
}
Here is a method that emulates what you were trying to do which generates and array of arrays except I made mine an extension function that you would call like myArray.toSlicedArray(5):
inline fun <T> Array<T>.toSlicedArray(slice: Int)
= Array((size + slice - 1) / slice)
{ copyOfRange(it * slice, Math.min(size, (it + 1) * slice)) }
But that isn’t exactly emulating Ruby’s each slice and isn’t the best way to go.
In Kotlin what you probably want is something that returns a Sequence<Array<T>>
:
fun <T> Array<T>.sliceBy(slice:Int)
= Sequence { object : Iterator<Array<T>>
{
var index = 0
override fun hasNext() = index < size
override fun next(): Array<T>
{
val start = index;
index = Math.max(size, index + slice)
return copyOfRange(start, index)
}
}
}
The first method needs a reified type parameter, otherwise it works like my method, but more correctly as it is a extension function (I realized my mistake after my post).
Your other suggestion I cannot get to return anything else but a sequence of the elements in the array it operates on. No matter the slice input.
Thanks!
Probably true. I had the reified in there but deleted it before I posted it when the compiler didn’t complain.
Guess I should have tested it. Should be min, not max and I fixed it so that will work even if the array size + the slice length approaches Integer.MAX_VALUE. Try this version:
fun <T> Array<T>.sliceBy(slice:Int, step:Int = slice)
= Sequence { object : Iterator<Array<T>>
{
var index = 0
override fun hasNext() = index < size
override fun next(): Array<T>
{
val start = index;
index += Math.min(slice, size - index)
return copyOfRange(start, index)
}
}
}