您可以将原始定义简化为:
mainDiagonal :: [[a]] -> [a]mainDiagonal [] = []mainDiagonal (x:xs) = head x : getDiagonal (map tail xs)
为此使用索引并没有多大错,这可以使您进一步简化为:
mainDiagonal xs = zipWith (!!) xs [0..]
基于数组的表示
您也可以使用由索引的Data.Array表示矩阵
(i,j)。这使您几乎逐字使用主要对角线的数学定义:
import Data.ArraymainDiagonal :: (Ix i) => Array (i, i) e -> [e]mainDiagonal xs = [ e | ((i,j),e) <- assocs xs, i == j ]
您可以这样使用:
-- n×n matrix helpermatrix n = listArray ((0,0),(n-1,n-1))> mainDiagonal $ matrix 3 [1..][1,5,9]
效率
的先前定义
mainDiagonal仍然无效:它仍然需要O(N²)个测试
i == j。与
zipWith版本类似,可以将其固定和概括如下:
mainDiagonal xs = (xs !) `map` zip [n..n'] [m..m']where ((n,m),(n',m')) = bounds xs
此版本仅索引数组O(N)次。(此外,它还适用于矩形矩阵,并且独立于索引基数。)



