2009-05-12 3 views
1

Ich möchte Liste der Zeichenfolgen wie unten gezeigt drucken.Wie man eine Liste der Zeichenketten mit 'unwords' in Haskell druckt?

|Name|Country|Age| 
------------------ 
|1 |USA |20 | 
|2 |UK  |19 | 

Ich konnte dies mit dem folgenden erreichen.

printfieldName :: [String] -> String 
printfieldName [] = [] 
printfieldName (x:xs) = "|" ++ x ++ "\t" ++ printfieldName (xs) 

Ist dies mit der eingebauten Funktion 'unwords' möglich? Ich konnte es mit 'unwords' drucken, konnte aber | nicht zwischen den Wörtern platzieren.

Antwort

4

Ich sehe es gibt einen zusätzlichen Raum zwischen ‚|‘ und Wort, so können Sie diese Funktion verwenden:

printfieldName x = unwords (map ((++) "|") x) ++ "|" 

kleine Erklärung:

(++) "|" - creates a function which take prefixes each word with "|", so 
(++) "|" "test" -> "|test" 

dann, map diese Funktion Umwandlung in eine Liste von Wörtern gilt es für ["|1", "|USA", "|20", ... ]

dann unwords schließt sich ihnen an in eine Zeichenfolge mit Leerzeichen zwischen Wörtern. Die ++ "|" wird benötigt, um intersperse genannt |

+0

im neuen Haskell, könnten Sie bitte den Fluss von erklären Die Funktion hast du geschrieben. Es klappt!:) danke – pier

+0

Cool! (++) "|" erstellt eine Funktion, die Präfixe für jedes Wort mit "|", also (++) "|" "test" -> "| test" Dann wendet 'map' diese Funktion auf eine Liste von Wörtern an, die sie in ["| 1", "| USA", "| 20", ...] konvertieren 'unwords 'verbindet sie zu einer Zeichenfolge mit Leerzeichen zwischen Wörtern. Das '++" | "'wird benötigt, um final | hinzuzufügen –

+0

Entschuldigung, alle Zeilenumbrüche in den Kommentaren wurden verloren. Ich bin neu hier :) –

4

Erstens würde ich es so schreiben:

printfieldName []  = [] 
printfieldName (x:xs) = "|" ++ x ++ "\t" ++ printfieldName xs 

Nun, eigentlich nicht, wie diese:

concatMap (\x -> '|' : x ++ "\t") 

Na ja, vielleicht eher wie:

concatMap (printf "|%s\t") 

OK . Kann es also als 'unwords' gemacht werden?

-- | 'unwords' is an inverse operation to 'words'. 
-- It joins words with separating spaces. 
unwords     :: [String] -> String 
unwords []    = "" 
unwords ws    = foldr1 (\w s -> w ++ ' ':s) ws 

Nein, aber sehen, wenn Sie concatMap als foldr schreiben ...

+0

i jetzt dieses Recht versucht, erhalte ich einen Fehler, wenn i execute Syntaxfehler in der Eingabe (unerwarteter umgekehrter Schrägstrich (Lambda)) printfieldName :: [String] -> String printfieldName [] = [] concatMap (\ x -> '|': x ++ "\ t") concatMap (printf "|% s \ t") dank – pier

+0

@dlna weitere Informationen Prelude benötigen Text.Printf> putStrLn $ concatMap (printf "|% s \ t") (Karte ([]) "Hallo") | h \t | e \t | l \t | l \t | o –

4

Data.List hat eine Funktion endgültig hinzufügen. Vielleicht kannst du das benutzen.

printfieldName xs = "|" ++ unwords (intersperse "|\t" xs) ++ "|" 
1

Vielleicht ein wenig übertrieben, was Sie gefragt, aber:

formatTable :: [String] -> [[String]] -> String 
formatTable header rows = 
    formatRow header ++ dashRow ++ concatMap formatRow rows 

    where formatRow cells = bracket '|' (spread cells) 
      dashRow   = bracket '+' (map (\n -> replicate n '-') widths) 
      bracket c cells = concatMap (c:) cells ++ (c:"\n") 

      spread cells = zipWith pad widths cells 
      pad n s   = take n (s ++ repeat ' ') 

      widths = foldr maxLengths (repeat 0) (header : rows) 
      maxLengths = zipWith (\c l -> max (length c) l) 

Dann, zum Beispiel:

> let h = words "Name Country Age" 
> let rows = map words ["1 USA 20", "2 UK 19"] 
> h 
["Name","Country","Age"] 
> rows 
[["1","USA","20"],["2","UK","19"]] 
> putStr $ formatTable h rows 
|Name|Country|Age| 
+----+-------+---+ 
|1 |USA |20 | 
|2 |UK  |19 |