小明正在用JavaScript写一个日志分析程序。该程序会将日志转化为CSV文件,以便在Excel等应用中加载为一个表格。现在他在生成表头上遇到了困难。
他需要实现如下一个方法:
function printLine(array) {
console.log(array.join(","));
}
function printHeader(obj) {
/* 使用 printLine 输出内容*/
}小明获取一个对象,需要根据这个对象的结构生成表头。例如:
{
Process: {
CpuUsage: 0
VirtualMemory: 0,
PrivateMemory: 0
},
Subscriptions: {
Order: {
TotalCount: 0,
LastMinute: 0,
Failed: 0
},
User: {
TotalCount: 0
LastMinute: 0
}
}
}由于表头仅和对象结构相关,因此无需关注字段的值。
输出为一行至多行文本,为CSV格式,字段之间以逗号隔开(简化问题起见,字段本身不包含逗号)。
如上输入,则需要得到以下输出:
Process,,,Subscriptions
CpuUsage,VirtualMemory,PrivateMemory,Order,,,User
,,,TotalCount,LastMinute,Failed,TotalCount,LastMinute
该CSV文件内容使用Excel打开便会得到以下表格(请忽略格式):
| Process | Subscriptions | ||||||
| CpuUsage | VirtualMemory | PrivateMemory | Order | User | |||
| TotalCount | LastMinute | Failed | TotalCount | LastMinute |
总而言之,是将对象结构转化为如上表头。
用Haskell试了下……省略了parse json的工作
{-# language DeriveFoldable, DeriveFunctor #-} module Main where data HeaderTree a = Leaf a | Node a [HeaderTree a] deriving(Show, Foldable, Functor) header = Node "Header" [process, sub] where process = Node "Process" [c, v, p] c = Leaf "CpuUsage" v = Leaf "VirtualMemory" p = Leaf "PrivateMemory" sub = Node "Subscription" [o, u] o = Node "Order" [t, l, f] t = Leaf "TotalCount" l = Leaf "LastMinute" f = Leaf "Failed" u = Node "User" [ut, ul] ut = Leaf "TotalCount" ul = Leaf "LastMinute" value :: HeaderTree a -> a value (Leaf v) = v value (Node v _) = v cvt :: (Show a) => HeaderTree a -> HeaderTree String cvt = fmap cellPrint . cvt' where cellPrint (content, len) = show content ++ replicate len ',' cvt' (Leaf x) = Leaf (x, 1) cvt' (Node x ns) = Node (x, nc) ns' where ns' = map cvt' ns nc = sum $ map (snd . value) ns' nextLevel :: HeaderTree String -> [HeaderTree String] nextLevel (Leaf _) = [Leaf ","] nextLevel (Node _ ns) = ns printHeader :: [HeaderTree String] -> [String] printHeader level | line == replicate (length line) ',' = [] | otherwise = line : printHeader (concatMap nextLevel level) where line = (reverse . (dropWhile (== ',')) . reverse) $ concatMap value level main = mapM_ putStrLn $ tail $ printHeader [cvt header]大概显示效果: