kotlinmatrixfunctional-programmingsubmatrix

In Kotlin, is there a way to use chunking to split a List<List<Int>> of size 1104 x 828 into 184 x 69 sublists of 6 x 12?


I have a List<List<Int>> in Kotlin of size 1104 x 828.

I want to split it into subgrids of size 6 x 12, of which there would be:

(1104 / 6) x (828 / 12) = 184 x 69

So, in essence, I need a List<List<List<List<Int>>>> of size 184 x 69 x 6 x 12.

Is there any easy way to to do this using chunking? I can easily get it to 184 x 6 x 69 x 12 by calling:

list.map { it.chunked(12) }.chunked(6)

but, of course, that's not the right dimensions.

If I have to, I'll use looping to make the 6 x 12 subgrids, but I was hoping that there was a way to get the list to the proper shape by just using chunking and perhaps mapping or some other list operations.

The goal is to perform a reduction on the 6 x 12 subgrids to end up with a 184 x 69 grid, so maybe there's an easier way to do this that I'm not seeing.


Solution

  • I finally figured out the answer thanks to lukas.j's response. Here is a function that takes a grid List<List<T>> with a subgridHeight and subgridWidth and partitions the grid into rows and columns of the specified height and width. I believe it can probably be made to work even if the subgridHeight and subgridWidth don't evenly divide the grid by passing partialWindows=true to the call to windowed.

    fun <T> subgrids(grid: List<List<T>>,
                     subgridHeight: Int,
                     subgridWidth: Int): List<List<List<List<T>>>> =
            grid
                .map { it.windowed(subgridHeight, subgridHeight) }
                .flatMap { it.withIndex() }
                .groupBy { it.index }
                .map { row -> row.value.map { it.value }.chunked(subgridWidth) }
    

    It's working fine for me.