2010-09-29 3 views
1

ont donc ceHaskell lignes de séparation dans la liste, y compris les lignes vides

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)) 

fonctionne ok sauf que je suppose que j'ai besoin des lignes vides aussi.

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

Je ne sais pas exactement comment je pourrais le faire. Des idées? Ai-je besoin de le réécrire avec autre chose?

Devrais-je utiliser une fonction d'ordre élevé comme foldr? Merci.

Je l'ai trouvé enfin merci.

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) 
+0

Pourquoi vos tuples doivent dupliquer l'index? Est-ce que 'lines' n'est pas ce que vous voulez? – Daenyth

+0

ne peut pas utiliser des lignes. devons créer notre propre fonction de lignes. Comment pourrais-je utiliser l'index? Je ne savais pas comment faire ça. – Matt

Répondre

2

Il est de jeter les lignes vides parce que vous faites dropWhile (=='\n) `, supprimer tous les sauts de ligne depuis le début de la chaîne.

Pour conserver les lignes vides, vous ne devez supprimer qu'un seul saut de ligne. La meilleure façon de le faire est d'utiliser la correspondance de motif:

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

Comme mentionné précédemment, vous ne recevez pas les lignes vides que vous taillez le nouveau personnage hors ligne du début de la chaîne. Il serait beaucoup plus facile de voir cela si splitLines a été refactorisé légèrement. Puisque vous ne pouvez pas utiliser lines, je commencerais par la création d'une simple fonction split (vous pouvez aussi utiliser Data.List.Split):

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

Avec cette fonction, splitLines est simple:

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

Honnêtement, je ne pense même pas que je peux utiliser split et break. Mais j'ai finalement compris. Merci. – Matt

Questions connexes