Haskell将行拆分为包含空行的列表

时间:2010-09-29 18:50:39

标签: list string haskell

所以有这个

type DocName = FilePath
type Line = (Int,String)
type Document = [Line]

splitLines :: String -> Document
splitLines [] = []
splitLines str = zip [0..(length listStr)] listStr
                                    where 
                                        listStr = [getLine] ++ map snd (splitLines getRest)
                                        getLine = (takeWhile (/='\n') str)
                                        getRest =  (dropWhile (=='\n') (dropWhile (/='\n') str))

工作正常,但我想我也需要空行。

splitLines "test\nthis\nstring\n" should be
[(0,"test"),(1,"this"),(2,"string"),(3,"")]

我不确定如何做到这一点。有任何想法吗? 我需要用别的东西重写它吗?

我应该使用像foldr这样的高阶函数吗? 感谢。

终于想通了。

splitLines :: String -> Document
splitLines "" = [(0,"")]
splitLines str = zip [0..(length listStr)] listStr
                                    where 
                                        listStr = [getLine] ++ map snd (splitLines getRest)
                                        getLine = takeWhile (/='\n') str
                                        getRest = tail (dropWhile (/='\n') str)

2 个答案:

答案 0 :(得分:2)

它正在丢弃空行,因为你正在执行dropWhile (=='\n)`,从字符串的开头删除所有换行符。

要保留空行,您只能删除一个换行符。最简单的方法是使用模式匹配:

getRest = case (dropWhile (/='\n') str) of
              (_:xs) -> xs
              [] -> []

答案 1 :(得分:2)

如上所述,当你从字符串的开头修剪新的行字符时,你不会得到空行。如果splitLines被轻微重构,那么看起来会容易得多。由于您无法使用lines,因此我首先要创建一个简单的split函数(您也可以使用Data.List.Split):

split :: (Eq a) => a -> [a] -> [[a]]
split a [] = [[]]
split a lst = (\(xs, y:ys) -> [xs] ++ split a ys) $ break (==a) lst

使用此功能,splitLines很简单:

splitLines :: String -> Document
splitLines [] = []
splitLines str = zip [0..] $ split '\n' str