Haskell如果否则列出理解

ruu*_*bel 5 haskell list-comprehension

我正试图以正确的方式打印出一块电路板,如下所示:

  1   2   3   4   5   6   7   8   9   10  11  12  13  14  15  16  17  18  
 1.   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .         
 2.   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .         
 3.   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .         
 4.   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .         
 5.   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .         
 6.   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .         
 7.   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .         
 8.   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .         
 9.   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .         
10.   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .         
11.   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .         
12.   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .         
13.   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .         
14.   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .         
15.   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .         
16.   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .         
17.   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .         
18.   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .         
Run Code Online (Sandbox Code Playgroud)

我在这里有列表理解

 ((concat [(""++show i)++"   " | i <- [1..n], i<10])++"\n")
Run Code Online (Sandbox Code Playgroud)

我可以正确地得到9个第一个数字,但问题出现的时候我想在我的理解中加上一个else语句.我似乎不知道该怎么做.所以为了让我的自我更清楚,我想用两位数做同样的事情,但唯一的区别是我想要两个空格而不是每个双位数之间的三个空格.

Wil*_*sem 2

列表推导式的左手接受任何 Haskell 表达式,因此我们可以在列表推导式的左手写if- then-并省略右手的条件:elsei < 10

concat [(""++show i)++if i < 10 then "   " else "  " | i <- [1..n]]++"\n"
Run Code Online (Sandbox Code Playgroud)

对于n = 15,则产生:

Prelude> concat [(""++show i)++if i < 10 then "   " else "  " | i <- [1..n]]++"\n"
"1   2   3   4   5   6   7   8   9   10  11  12  13  14  15  \n"
Run Code Online (Sandbox Code Playgroud)

我们还可以删除""++列表理解左侧的部分,因为这基本上是一个no 操作

concat [show i ++ if i < 10 then "   " else "  " | i <- [1..n]] ++ "\n"
Run Code Online (Sandbox Code Playgroud)

然而上面的代码并不是很优雅:如果i = 123,那么我们仍然会遇到麻烦。我们可以计算 的长度show,计算4-l(使用l长度),并将其添加为额外间距。例如:

concat [s ++ replicate (4-length s) ' ' | i <- [1..n], let s = show i] ++ "\n"
Run Code Online (Sandbox Code Playgroud)

还有一些更专用的格式化和连接函数,但由于练习可能是为了熟悉列表,所以我认为这超出了这里的范围。

就像@4castle所说,我们可以使用例如printf

import Text.Printf(printf)

concatMap (printf "%-4d") [1..n] ++ "\n"
Run Code Online (Sandbox Code Playgroud)