如何在Haskell中的新行上打印部分列表

时间:2013-05-05 00:07:57

标签: list haskell

这可能是一个愚蠢的问题,但我对Haskell很新。 (我刚开始几小时前就开始使用它了。)

所以我的问题是我有一个包含4个元素的列表,我需要在一行上打印两个,在新行上打印两个。

以下是清单:

let list1 = ["#", "@", "#", "#"]

我需要输出看起来像这样:

#@
##

我知道我可以使用以下内容在新行上打印每个元素:

mapM_ putStrLn list1 

但我不确定如何调整此选项仅用于在新行上打印列表的部分

4 个答案:

答案 0 :(得分:4)

你想要Data.Text.chunksOf这样的任意列表,我从来没有见过任何列表,所以我总是重新实现它。

import Data.List (unfoldr)

-- This version ensures that the output consists of lists 
-- of equal length. To do so, it trims the input.
chunksOf :: Int -> [a] -> [[a]]
chunksOf n = unfoldr (test . splitAt n) where
  test (_, []) = Nothing
  test x       = Just x

然后我们可以将您的[String]转换为[[String]],这是一个列表,每个列表对应一行的String个组件。我们在该列表上map concat合并其组件中的每一行,然后使用unlines将它们粘合在一起。

grid :: Int -> [String] -> String
grid n = unlines . map concat . chunksOf n

然后我们可以根据需要打印该字符串

main :: IO ()
main = putStrLn $ grid 2 list1

编辑:显然在相当受欢迎的库Data.List.Split中有一个chunksOf。根据我的知识,他们的版本与我的相同,尽管它的实现方式略有不同。我们两个都应该满足

chunksOf n xs ++ chunksOf n ys == chunksOf n (xs ++ ys)

每当length xs `mod` n == 0

答案 1 :(得分:0)

你可以这样做:

mapM_ putStrLn [(take 2 list1), (drop 2 list1)]

其中takedrop返回包含预期元素数量的列表。 take 2需要两个元素,而drop 2会删除前两个元素。

答案 2 :(得分:0)

查看 tel 链接Data.List.Split,可以使用 chop 构建另一种解决方案。
在lib中定义如下,

chop :: ([a] -> (b, [a])) -> [a] -> [b]
chop _ [] = []
chop f as = b : chop f as'
  where (b, as') = f as

然后按照simeon的建议,我们以这一个班轮结束,

let fun n = mapM_ putStrLn . chop (splitAt n)

chop似乎是一个很好的功能,足以在这里提到以说明另一种解决方案。 (展开也很棒)。

答案 3 :(得分:0)

初学者尝试:

myOut :: [String] -> IO ()
myOut [] = putStr "\n" 
myOut (x:xs) = 
    do if x=="@"
       then putStrLn x
       else putStr x

       myOut xs



ghci>myOut ["#", "@", "#", "#"]
#@
##
ghci>