二维列表如下所示:

1 | 2 | 3
- - - - -
4 | 5 | 6
- - - - -
7 | 8 | 9
或纯属Haskell
[ [1,2,3], [4,5,6], [7,8,9] ]
diagonals [ [1,2,3], [4,5,6], [7,8,9] ]的预期输出为
[ [1], [4, 2], [7, 5, 3], [8, 6], [9] ]
编写allDiagonals(包括反对角线)很简单:
allDiagonals :: [[a]] -> [[a]]
allDiagonals xss = (diagonals xss) ++ (diagonals (rotate90 xss))
我对这个问题的研究
StackOverflow上的类似问题
  • Python这个问题与Python中的相同问题有关,但是Python和Haskell有很大不同,因此该问题的答案与我无关。
  • Only one这个问题和答案在Haskell中,但仅关于中央对角线。

  • Hoogle
    搜索[[a]] -> [[a]]没有给我有趣的结果。
    独立思考
    我认为索引遵循的是基数x中的一种计数,其中x是矩阵中的维数,请看:
    1 | 2
    - - -
    3 | 4
    
    对角线为[ [1], [3, 2], [4] ]
  • 1可在matrix[0][0]上找到
  • 3可在matrix[1][0]上找到
  • 2可在matrix[0][1]上找到
  • 1可在matrix[1][1]上找到

  • 这类似于以2为基数最多3,即矩阵大小减去1。但这太模糊了,无法翻译成代码。

    最佳答案

    universe-base-1.0.2.1开始,您可以简单地调用 diagonals 函数:

    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]
    

    关键思想是,我们保留两个列表:一个尚未开始检查的矩形块,以及一个五边形块(切出左上三角形的矩形!)。对于五边形块,从每个列表中选择第一个元素会给我们另一个对角线。然后,我们可以在删除该对角线后从矩形未检查的块中添加一个新行到剩余的行。

    该实现可能看起来有点不自然,但它的意图是非常高效和懒惰:我们要列出的唯一内容是将它们分解为头部和尾部,因此该元素的总数应为O(n)。矩阵;并且我们在完成结构分解后就立即生成元素,因此对于垃圾回收而言,它是非常懒惰/友好的。它对于无限大的矩阵也适用。

    (我仅为您推送了此发行版:您可以使用的最接近的方式是使用diagonal,它只会为您提供[1,4,2,7,5,3,8,6,9]而没有您想要的额外结构。)

    关于haskell - 在Haskell中获取矩阵的所有对角线,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/32465776/

    10-12 20:40