2009-05-12 6 views
1

Je veux imprimer la liste des chaînes comme montré ci-dessous.Comment imprimer une liste de chaînes en utilisant 'unwords' dans Haskell?

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

J'ai été capable d'atteindre ceci en utilisant ce qui suit. Est-il possible de réaliser ceci en utilisant la fonction intégrée 'unwords'. Je pouvais l'imprimer en utilisant 'unwords' mais je ne pouvais pas placer | entre les mots.

Répondre

4

Je vois qu'il ya un espace supplémentaire entre « | » et le mot, vous pouvez utiliser cette fonction:

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

petite explication:

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

alors, map applique cette fonction à une liste de mots de conversion à ["|1", "|USA", "|20", ... ]

puis unwords les rejoint dans une chaîne avec des espaces entre les mots. Le ++ "|" est nécessaire pour ajouter final |

+0

im nouveau à HASKELL, pourriez-vous s'il vous plaît expliquer le flux de la fonction que vous avez écrite. Ça marche!:) merci – pier

+0

Cool! (++) "|" crée une fonction qui prend les préfixes de chaque mot avec "|", donc (++) "|" "test" -> "| test" puis, 'map 'applique cette fonction à une liste de mots la convertissant en [" | 1 "," | USA "," | 20 ", ...] puis 'unwords 'les joint dans une chaîne avec des espaces entre les mots. Le '++" | "'est nécessaire pour ajouter final | –

+0

Désolé, toutes les nouvelles lignes dans les commentaires ont été perdues. Je suis nouveau ici :) –

4

Tout d'abord, je voudrais écrire comme ceci:

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

Eh bien, en fait, non, comme ceci:

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

Eh bien, peut-être plus comme:

concatMap (printf "|%s\t") 

OK . Alors peut-il être fait comme «unwords»?

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

Non, mais si vous pouvez écrire concatMap comme foldr ...

+0

j'ai essayé ce moment, je reçois une erreur quand je execute Erreur de syntaxe en entrée (barre oblique inverse inattendue (lambda)) nom_impression :: [Chaîne] -> Chaîne nom_imprimante [] = [] concatMap (\ x -> '|': x ++ "\ t") concatMap (printf "|% s \ t") grâce – pier

+0

@dlna ont besoin de plus d'informations Prelude Text.Printf> putStrLn $ concatMap (printf "|% s \ t") (carte (: []) "bonjour") | h \t | e \t | l \t | l \t | o –

4

Data.List a une fonction appelée intersperse. Peut-être que vous pouvez l'utiliser.

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

Peut-être un peu plus haut de ce que vous avez demandé, mais:

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) 

Ensuite, par exemple:

> 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 | 
Questions connexes