【问题标题】:Haskell read first n linesHaskell 读取前 n 行
【发布时间】:2012-06-01 22:59:13
【问题描述】:
我正在尝试学习 Haskell 以适应函数式编程语言。我决定在interviewstreet 尝试一些问题来开始。我在从标准输入读取和使用 haskell 的惰性 io 执行一般 io 时遇到问题。
大多数问题的数据来自标准输入,格式如下:
n
data line 1
data line 2
data line 3
...
data line n
其中 n 是来自标准输入的后续行数,下一行是数据。
如何在 n 行的每一行上一次运行我的程序并将解决方案返回到标准输出?
我知道 stdin 输入不会很大,但我要求一次评估每一行,假装输入大于内存容量,只是为了学习如何使用 haskell。
【问题讨论】:
标签:
haskell
functional-programming
stdout
stdin
【解决方案1】:
您可以将interact 与lines 结合使用,一次处理一行来自标准输入的数据。这是一个示例程序,它使用interact 访问标准输入,lines 在每个换行符上拆分数据,一个列表推导式将函数perLine 应用于输入的每一行,以及unlines 将输出从perLine 又聚在一起了。
main = interact processInput
processInput input = unlines [perLine line | line <- lines input]
perLine line = reverse line -- do whatever you want to 'line' here!
您无需担心通过标准输入获得的数据大小; Haskell 的懒惰确保您随时只将实际正在处理的部分保留在内存中。
编辑:如果您仍想只处理第一行 n,您可以使用上面示例中的 take 函数,如下所示:
processInput input = unlines [perLine line | line <- take 10 (lines input)]
这将在前十行被读取和处理后终止程序。
【解决方案2】:
你也可以使用简单的递归:
getMultipleLines :: Int -> IO [String]
getMultipleLines n
| n <= 0 = return []
| otherwise = do
x <- getLine
xs <- getMultipleLines (n-1)
return (x:xs)
然后在你的 main 中使用它:
main :: IO ()
main = do
line <- getLine
let numLines = read line :: Int
inputs <- getMultipleLines numLines