Haskell中实现[[Double]]类型列表的跨行索引式打印
解决Haskell中[[Double]]类型数据的跨行索引打印问题
我曾成功实现过两个子列表的打印操作,但现已遗忘具体步骤,目前需要处理任意数量等长子列表的
[[Double]]类型数据。输入示例[[1,2,3],[1,2,3],[1,2,3]]的期望输出为:1 1 1 2 2 2 3 3 3我计划使用
mapM_,并通过printf控制打印格式,但当前代码是按子列表逐行打印,而非按索引跨行打印。现有代码如下:import Text.Printf ( printf ) print_row :: Double -> IO () print_row r = do printf "%9.6f" r print_rows :: [[Double]] -> Int -> IO () print_rows r i = do mapM_ print_row (r !! i) main :: IO () main = do let rs = [[1,2,3],[1,2,3],[1,2,3]] n = length rs - 1 mapM_ (print_rows rs) [0..n]
解决方案
核心思路是先转置列表——把原列表的列转换为行,这样就能直接按行打印转置后的每个子列表。Haskell的Data.List模块提供了transpose函数可以完成这个操作。
修改后的代码如下:
import Text.Printf (printf) import Data.List (transpose) -- 打印单个元素,带指定格式 printElement :: Double -> IO () printElement x = printf "%9.6f" x -- 打印一行元素:逐个打印元素后换行 printTransposedRow :: [Double] -> IO () printTransposedRow row = do mapM_ printElement row putStrLn "" main :: IO () main = do let rs = [[1,2,3],[1,2,3],[1,2,3]] transposedRs = transpose rs mapM_ printTransposedRow transposedRs
代码说明
transpose rs会将输入的[[1,2,3],[1,2,3],[1,2,3]]转换为[[1,1,1],[2,2,2],[3,3,3]],完全匹配期望的每行输出结构。printTransposedRow函数处理单行输出:先用mapM_ printElement打印该行所有元素,再通过putStrLn ""换行,保证每行输出独立。- 最后用
mapM_ printTransposedRow遍历转置后的列表,逐行打印即可实现需求。
不依赖内置transpose的实现(可选)
如果不想依赖Data.List的transpose,可以自己实现针对等长子列表的转置逻辑:
transpose' :: [[a]] -> [[a]] transpose' [] = [] transpose' ([]:xs) = transpose' xs transpose' ((x:xs):xss) = (x : map head xss) : transpose' (xs : map tail xss)
将代码中的transpose替换为transpose'即可,效果完全一致。
内容的提问来源于stack exchange,提问作者Pompan
相关产品推荐
相关产品推荐

