Haskell - 如何将矩阵(二维数组)分成几组

下面有一个二维矩阵:

mat = [[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]]

我想把它翻译成4组:

output = [[1,2,5,6],[3,4,7,8],[9,10,13,14],[11,12,15,16]]

在 Java 或 Python 等其他(命令式)编程语言中,我可以轻松地创建 4 个新列表并从每个子矩阵的左上角位置 (i,j) 开始迭代以将元素添加到. 但是在 Haskell 中,我不知道如何实现我想要的,因为它不支持循环,递归循环 (x:xs) 似乎对这种情况没有帮助。

最佳答案

编写 chunksOf 是很有用的,它将一个列表分成几部分,每个部分 给定大小。

chunksOf :: Int -> [a] -> [[a]]
chunksOf _ [] = []
chunksOf n xs = ys : chunksOf n zs
  where
    (ys, zs) = splitAt n xs

例如:

> chunksOf 2 "potato"
["po","ta","to"]

(如果你了解unfoldr,你也可以写的很好chunksOf 使用那个。)

我们可以使用 chunksOf 2 来获取每行两行的组,[[1,2,3,4], [5,6,7,8]][[9,10,11,12], [13,14,15,16]]

从这些我们想要对列进行分组 - 我们可以通过 转置、分组行,然后再次转置每组。

(转置在Data.List中。)

例如,在第一行组,我们转置得到

[[1, 5], [2, 6], [3, 7], [4, 8]]

然后 chunksOf 2 给了我们

[[[1, 5], [2, 6]], [[3, 7], [4, 8]]]

然后我们映射转置得到

[[[1, 2], [5, 6]], [[3, 4], [7, 8]]]

所以现在我们有了 2x2 子矩阵,剩下的就是得到你想要的 想要的是用 concat 把每一个都压平。

综合起来:

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

https://stackoverflow.com/questions/64132032/

相关文章:

swift - 在 RealityKit 中启用手势

reactjs - 不能在 JSX 属性中使用 bool 值

python - 重复值 n 次,n 在一个数组中

java - 检查一个数组列表是否包含两个字符串

python - 为什么 python 的 "gc.collect()"没有按预期工作?

python-3.x - Pygame - 不存在 "Setup"文件,正在运行 "buildcon

c# - 无法将 TextMeshPro 文本获取到 Unity 中的变量槽

python - 如何使用 numba 在 GPU 上推广快速矩阵乘法

javascript - 使用 useEffect 加载脚本

r - 按列计算唯一值