Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ssis/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Haskell中求矩阵的所有对角线_Haskell_Matrix - Fatal编程技术网

在Haskell中求矩阵的所有对角线

在Haskell中求矩阵的所有对角线,haskell,matrix,Haskell,Matrix,二维列表如下所示: 1 | 2 | 3 - - - - - 4 | 5 | 6 - - - - - 7 | 8 | 9 还是纯哈斯克尔 [ [1,2,3], [4,5,6], [7,8,9] ] 对角线[[1,2,3],[4,5,6],[7,8,9]]的预期输出为 [ [1], [4, 2], [7, 5, 3], [8, 6], [9] ] 编写所有对角线(包括反对角线)就很简单了: allDiagonals :: [[a]] -> [[a]] allDiagonals xss =

二维列表如下所示:

1 | 2 | 3
- - - - -
4 | 5 | 6
- - - - -
7 | 8 | 9
还是纯哈斯克尔

[ [1,2,3], [4,5,6], [7,8,9] ]
对角线[[1,2,3],[4,5,6],[7,8,9]]的预期输出为

[ [1], [4, 2], [7, 5, 3], [8, 6], [9] ]
编写
所有对角线
(包括反对角线)就很简单了:

allDiagonals :: [[a]] -> [[a]]
allDiagonals xss = (diagonals xss) ++ (diagonals (rotate90 xss))
我对这个问题的研究 StackOverflow的类似问题

  • 这个问题与Python中的相同问题有关,但是Python和Haskell非常不同,所以这个问题的答案与我无关

  • 这个问题和答案是用Haskell写成的,但只涉及中心对角线

Hoogle

搜索
[[a]]->[[a]]
没有给我任何有趣的结果

独立思考

我认为索引遵循基数x中的一种计数,其中x是矩阵中的维数,请看:

1 | 2
- - -
3 | 4
对角线是
[[1],[3,2],[4]]

  • 1
    可在
    矩阵[0][0]
  • 3
    可在
    矩阵[1][0]
  • 2
    可在
    矩阵[0][1]
  • 1
    可在
    矩阵[1][1]
这类似于从基数2到3的计数,即矩阵大小减1。但这太模糊了,无法翻译成代码。

这里有一种方法:

f :: [[a]] -> [[a]]
f vals = 
    let n = length vals
    in [[(vals !! y) !! x | x <- [0..(n - 1)], 
                            y <- [0..(n - 1)], 
                            x + y == k] 
        | k <- [0 .. 2*(n-1)]]
f::[[a]]->[[a]]
f VAL=
设n=长度VAL

在[[(vals!!y)!!x | x中,这里是一个递归版本,假设输入总是格式良好的:

diagonals []       = []
diagonals ([]:xss) = xss
diagonals xss      = zipWith (++) (map ((:[]) . head) xss ++ repeat [])
                                  ([]:(diagonals (map tail xss)))
它是递归工作的,从一列到另一列。一列的值与矩阵中的对角线相结合,减少一列,移动一行,得到对角线。希望这个解释有意义

举例说明:

diagonals [[1,2,3],[4,5,6],[7,8,9]]
= zipWith (++) [[1],[4],[7],[],[],...] [[],[2],[5,3],[8,6],[9]]
= [[1],[4,2],[7,5,3],[8,6],[9]]
另一个对行而不是列起作用的版本,但基于相同的思想:

diagonals []       = repeat []
diagonals (xs:xss) = takeWhile (not . null) $
    zipWith (++) (map (:[]) xs ++ repeat [])
                 ([]:diagonals xss)
与指定的结果相比,生成的对角线是反向的。当然,这可以通过应用
映射反向

导入数据。列表来修复
import Data.List

rotate90 = reverse . transpose
rotate180 = rotate90 . rotate90

diagonals = (++) <$> transpose . zipWith drop [0..]
                 <*> transpose . zipWith drop [1..] . rotate180
rotate90=反向转置 旋转180=旋转90。旋转90 对角线=(++)转置.zipWith drop[0..] 转置。带下拉[1..]的拉链。旋转180
它首先获取主(
[1,5,9]
)和上对角线(
[2,6]
[3]
),然后获取下对角线:
[8,4]
[7]

如果您关心排序(即,您认为应该说
[4,8]
而不是
[8,4]
),请在最后一行插入
映射反向。

从开始,您可以简单地调用该函数:

Data.Universe.Helpers> diagonals [ [1,2,3], [4,5,6], [7,8,9] ]
[[1],[4,2],[7,5,3],[8,6],[9]]
完整的实现如下所示:

diagonals :: [[a]] -> [[a]]
diagonals = tail . go [] where
    -- it is critical for some applications that we start producing answers
    -- before inspecting es_
    go b es_ = [h | h:_ <- b] : case es_ of
        []   -> transpose ts
        e:es -> go (e:ts) es
        where ts = [t | _:t <- b]
对角线::[[a]]->[[a]]
对角线=尾部。转到[]哪里
--对于某些应用程序,我们开始生成答案是至关重要的
--检查前_
go b es|=[h | h:uu转置ts
e:es->go(e:ts)es
式中,ts=[t | |:t彼此的解决方案:

diagonals = map concat
          . transpose
          . zipWith (\ns xs -> ns ++ map (:[]) xs)
                    (iterate ([]:) [])
基本上,我们转向

[1, 2, 3]
[4, 5, 6]
[7, 8, 9]
进入

然后
transpose
concat
列表。对角线的顺序相反


但是这不是很有效,也不适用于无限列表。

谢谢,我对这个响应的速度和清晰性印象深刻。但是请将
f
重命名为
diagonals
,因为Haskell已经有了足够多的单字母名称;但是我碰巧偏爱这个字母:p--->对不起,我不得不说我不喜欢“我不喜欢这个解决方案。首先,列表中有太多的
!!
,应该尽可能避免出现这种情况(与向量不同)。其次,它会循环
y@chi这些都是正确的观点。我不反对其中任何一点。它们并不影响我对这个特定解决方案的看法,这就是为什么我仅将其限定为“单向”要解决它。请随意优化它。Haskell更自然的思考方式是:给定第一行和由其余行组成的矩阵上的
对角线的结果,我们如何在整个原始矩阵上构造
对角线的结果?数学我实际上不关心排序
rotate180
似乎有点奇怪。不会
映射反向。反向
做这个把戏吗?使用
tail
在某种程度上是必要的吗?@dfeuer不是必要的;但总是从空列表开始似乎并不是非常有用。有其他方法跳过它吗?@dfeuer几乎可以肯定!你有什么想法吗?我只是不喜欢usi除非懒惰需要,否则使用部分函数来实现全部函数。在这种情况下,我猜您可以专门处理第一步来避免它,但我没有尝试过。
[1, 2, 3]
[4, 5, 6]
[7, 8, 9]
[[1], [2], [3]]
[[] , [4], [5], [6]]
[[] , [] , [7], [8], [9]]