我在下面有一个二维矩阵:
mat = [[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]]
Run Code Online (Sandbox Code Playgroud)
我想把它翻译成4组:
output = [[1,2,5,6],[3,4,7,8],[9,10,13,14],[11,12,15,16]]
Run Code Online (Sandbox Code Playgroud)
在 Java 或 Python 等其他(命令式)编程语言中,我可以轻松创建 4 个新列表,并从(i,j)每个子矩阵的左上角开始迭代以添加元素。但在 Haskell 中,我不知道如何实现我想要的因为它不支持 for 循环并且递归循环(x:xs)似乎对这种情况没有帮助。
It's useful to write chunksOf which breaks a list into parts, each
of a given size.
chunksOf :: Int -> [a] -> [[a]]
chunksOf _ [] = []
chunksOf n xs = ys : chunksOf n zs
where
(ys, zs) = splitAt n xs
Run Code Online (Sandbox Code Playgroud)
For example:
> chunksOf 2 "potato"
["po","ta","to"]
Run Code Online (Sandbox Code Playgroud)
(If you know about unfoldr, you can also write chunksOf nicely
using that.)
We can use chunksOf 2 to get groups of two rows each, [[1,2,3,4], [5,6,7,8]] and [[9,10,11,12], [13,14,15,16]].
From these we want to group the columns - we can do this by transposing, grouping rows, then transposing each group back again.
(transpose is in Data.List.)
For example, on the first row group, we transpose to get
[[1, 5], [2, 6], [3, 7], [4, 8]]
Run Code Online (Sandbox Code Playgroud)
Then chunksOf 2 gives us
[[[1, 5], [2, 6]], [[3, 7], [4, 8]]]
Run Code Online (Sandbox Code Playgroud)
Then we map transpose to get
[[[1, 2], [5, 6]], [[3, 4], [7, 8]]]
Run Code Online (Sandbox Code Playgroud)
So now we have 2x2 submatrices and the only thing left to get what you
wanted is to flatten each one with concat.
Putting it all together:
f :: Int -> [[a]] -> [[a]]
f size = map concat . subMatrices size
subMatrices :: Int -> [[a]] -> [[[a]]]
subMatrices size = concatMap subsFromRowGroup . rowGroups
where
rowGroups = chunksOf size
subsFromRowGroup = map transpose . chunksOf size . transpose
Run Code Online (Sandbox Code Playgroud)