将列表转换为矩阵(Haskell)

3
我正在尝试从接收到一个始终从0开始的计数器Int(i)、另一个Int(n)作为每一行长度以及要转换为矩阵的列表中将列表转换为数组(列表的列表)的函数中进行转换。
createMatrix :: (Int, Int, [Int]) -> [[Int]]
createMatrix (i, n, ([])) = []
createMatrix (i, n, (x:y)) = if (i < n) then [x] : createMatrix (i+1, n, (y))
                            else  [] ++ createMatrix (0, n, (x:y))

这将输出以下内容:
[[1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],[12],[13],[14],[15],[16],[17],[18]]

当它应该是这样的:
[[1,2,3,4,5,6],[7,8,9,10,11,12],[13,14,15,16,17,18]]

如果n等于6

有没有人有什么想法,可能是我做错了什么?我尝试了几种方法,但没有找到解决方案。

谢谢


1
类似 createMatrix n xs = take n xs : createMatrix n (drop n xs) 这样就足够了。您不需要两个计数器;另一个计数器是由 takedrop 内部维护的。 - chepner
嘿!谢谢,但我必须在不使用take和drop的情况下解决它! - Fcr
答案有点简短。首先是 createMatrix _ [] = [],然后是 createMatrix n xs = take n xs : createMatrix n (drop n xs) - user855443
2个回答

2
当你写 [x]:createMatrix (...) 时,你总是在输出中添加一个完整的新列表。而当你执行 [] ++ createMatrix (...) 时,你并没有对结果做出任何改变;连接一个空列表什么也不会发生。
你希望将 x 前置到 createMatrix (...) 结果中的第一个列表中,而不是将 [x] 前置到整个结果中。
else 分支中,你希望前置一个新的空列表,而不是尝试使用 ++ 连接两个列表。

类似这样的代码?createMatrix (i, n, (x:y)) = 如果 (i < n) 那么 x : createMatrix (i+1, n, (y)) else [] : createMatrix (0, n, (x:y)) - Fcr
所以在这种情况下,您将x和[]都添加到结果列表的开头。如果Haskell支持异构列表,您最终会得到:[1,2,3,4,5,6,[],7,8,9,10,11,12,[],13,14,15,16,17,18,[]],但它不支持,因此这将导致类型错误。您需要从递归结果中获取第一个列表,将x添加到其中,并将其放回结果中。 - Izaak Weiss

1
一个不使用 counter 的替代方案,只需在给定的 n 上拆分您的列表:
matrixEvery :: Int -> [a] -> [[a]]
matrixEvery _ [] = []
matrixEvery n xs = as : matrixEvery n bs
  where (as,bs) = matrixEvery n xs

递归被用来代替传递计数器。唯一的缺点是,如果你想让矩阵都是相等的大小,这种方法就不起作用了,但它可以让你更接近目标 :)

GHC 9.0.2在这个解决方案中无法工作。我猜是某个地方缺少了take n - user855443

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接