Skip to content

Instantly share code, notes, and snippets.

@YusukeHosonuma
Last active August 22, 2016 00:45
Show Gist options
  • Save YusukeHosonuma/408dd5f6ef80a69ae6d74a0a98135d13 to your computer and use it in GitHub Desktop.
Save YusukeHosonuma/408dd5f6ef80a69ae6d74a0a98135d13 to your computer and use it in GitHub Desktop.
CSVFormatter.hs
-- CSVFormatter.hs
{-
Input:
Name,Birthday,Height
Suzukaze Aoba,2/2,149cm
Ko Yagami,8/2,164cm
Rin Toyama,12/3,158cm
Output:
Name | Birthday | Height
-----------------------------------
Suzukaze Aoba | 2/2 | 149cm
Ko Yagami | 8/2 | 164cm
Rin Toyama | 12/3 | 158cm
-}
import Data.Text (split, pack, unpack)
import Data.List
-- | Main
main = do
contents <- getContents
let ls = lines contents
result = unlines . formatCSVLines . parseCSV $ ls
putStrLn result
-- | CSV型
type CSV = [[String]]
-- | CSVをパース
parseCSV :: [String] -> CSV
parseCSV = map $ map unpack . split (== ',') . pack
-- | CSVをフォーマット
formatCSVLines :: CSV -> [String]
formatCSVLines csv = insertSeparator csvLines
where csvLines = map (intercalate " | ") $ spaced
spaced = map (\xs -> zipWith padRight xs $ maxLengths csv) csv
-- | 1行目と2行目の間にセパレータ(----)を入れる
insertSeparator :: [String] -> [String]
insertSeparator xs = head xs : replicate (length $ head xs) '-' : tail xs
-- | CSVの各カラムの最大桁数のリストを取得
maxLengths :: CSV -> [Int]
maxLengths = foldl (\acc xs -> zipWith max acc (map length xs)) [0..]
-- | 指定された桁数になるようにスペースを埋める
padRight :: String -> Int -> String
padRight s n = s ++ replicate (n - length s) ' '
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment