How to print a list of strings using "unwords" in Haskell?

I want to print a list of strings as shown below.

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

      

I was able to achieve this using the following.

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

      

Is it possible to achieve this using the built-in "unwords" function. I was able to print it out with "unwords" but couldn't fit |

between words.

+1


a source to share


4 answers


I see there is extra space between '|' and a word, so you can use this function:

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

      

little explanation:



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

      

then map

applies this function to the list of words, converting them to["|1", "|USA", "|20", ... ]

then unwords

concatenates them into a string with spaces between words. ++ "|"

need to add the final|

+4


a source


First, I would write it like this:

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

      

Well, actually, no, like this:

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

      

Well, maybe more like:



concatMap (printf "|%s\t")

      

OK. So can this be done as "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

      

No. But see if you can write concatMap as foldr ...

+4


a source


Data.List

has a feature called intersperse. Perhaps you can use this.

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

      

+4


a source


Possibly slightly higher than what you asked, but:

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)

      

Then, for example:

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

      

+1


a source







All Articles