几天前刚刚开始学习Haskell,我遇到了一些问题。第一个问题涉及打印数字列表。期望的行为如下:
输入:[1,2,3,4,5,6]
输出:1 2 3 | 4 5 6所以它是一个简单的概念,我只需要用“|”输出列表的元素在每三个数字之间插入符号,但我不能为我的生活弄明白。似乎我尝试过的大多数东西都涉及到字符串,即使我能够将列表添加到字符串中,如[“1”,“2”,“3”,...]所有的方法我都是尝试在各自的行上打印数字,这不是我需要的。
非常感谢任何帮助。
答案 0 :(得分:5)
使用split包(最近添加到Haskell平台):
> import Data.List -- for intercalate
> import Data.List.Split -- for chunksOf
> intercalate " | " . map unwords . chunksOf 3 $ map show [1..7]
"1 2 3 | 4 5 6 | 7"
相关文档:chunksOf
,unwords
,intercalate
。
答案 1 :(得分:3)
这是一种方式。
import Data.List (cycle)
format :: Show a => [a] -> String
format = concat . zipWith (++) ("" : cycle [" ", " ", " | "]) . map show
这确实有一个缺点,即分组成三个一组是硬编码的,但要概括起来并不太难。
答案 2 :(得分:2)
你可以做到
threes [] = ""
threes xs = let (front,rest) = splitAt 3 xs in
unwords (map show front) ++
if null rest then "" else " | " ++ threes rest
给
*Main> threes [1..10]
"1 2 3 | 4 5 6 | 7 8 9 | 10"
我使用的功能:
splitAt :: Int -> [a] -> ([a], [a])
-- splitAt 2 "Hello Mum" = ("He","llo Mum")
unwords :: [String] -> String
-- unwords ["Hello","there","everyone"]
-- = "Hello there everyone"
null :: [a] -> Bool
null [] = True
null _ = False
答案 3 :(得分:1)
第一部分是最简单的,您需要将数字转换为String
s,
format :: (Num a, Show a) => [a] -> String
format xs = result
where
strings = map show xs
那样做。然后我们需要将任何列表拆分为三个(更通用的,n
)元素的块。 splitAt
将列表拆分为所需数量的元素的前部 - 如果列表足够长 - 则为余数。在剩余部分上迭代该过程,而不是空的会导致期望的结果。
chunk :: Int -> [a] -> [[a]]
chunk _ [] = []
chunk n xs = ys : chunk n zs
where
(ys, zs) = splitAt n xs
这是一个反复出现的模式,所以有一个组合器,我们也可以写
import Data.List (unfoldr)
chunk :: Int -> [a] -> [[a]]
chunk n = unfoldr split
where
split [] = Nothing
split xs = Just $ splitAt n xs
我们可以继续format
,
format :: (Num a, Show a) => [a] -> String
format xs = result
where
strings = map show xs
chunks = chunk 3 strings
然后我们需要在所有块之间插入"|"
,这是由intercalate
从Data.List
完成的,最后,将所有字符串与它们之间的空格连接起来,这就是{{1是的,所以
unwords
或者
format :: (Num a, Show a) => [a] -> String
format xs = result
where
strings = map show xs
chunks = chunk 3 strings
result = unwords $ intercalate "|" chunks