- [(教师,主题,类,extrasub)]
test =[("Sam","Maths","Std5","PE"),
("Sam","Maths","Std7","PE"),
("Sam","geography","Std6","PE"),
("Jake","English","Std9","Red Cross"),
("Jake","English","Std9","Guards")]
看起来应该是这样的
Teacher Subject Class ExtraClass
Sam Maths Std5 PE
Std7
Geography Std6
Jake English Std9 Red Cross
Guards
我希望输出像这样
[
("Jake","English","Std9","Red Cross"),
("","","","Guards"),
("Sam","Maths","Std7","PE"),
("","","Std5",""),
("","geography","Std6","PE")]
test2 :: [([Char], [Char], [Char], [Char])]
test2 = test3 $ concat $ groupBy (\(x,_,_,_) (y,_,_,_) -> x==y) (sort test1)
test3 [] = []
test3 [x] = []
test3 ((a1,b1,c1,d1):(a2,b2,c2,d2):xs) =
if(a1==a2 && b1== b2&& d1==d2)
then [("","",c1,d1)]
else if (a1==a2)
then [("","",c1,d1)]
else [("",b1,c1,d1)]
我正在考虑使用foldl的这种方法,但无法得到它。关于如何进行此任何建议
答案 0 :(得分:3)
实际上这很难。你必须解决两个问题:
如何转换输入,以便将连续行中的重复字段替换为空白 空间。
如何在漂亮的列中打印结果。
让我们逐一讨论这些问题。
转换输入。
我们该怎么办?如果任何给定的连续单元格中存在重复值 列,我们想用空格替换所有这些,除了第一个。所以,我们可能会这样做 像这样:
将每列分析为列表。
如果存在重复值,请仅保留第一个值,并将所有其他值替换为空白 空间。
棘手的时刻是,如果第一列的值发生变化,我们想停止 消隐单元并至少打印一行。为了确保这一点,我们可能会打破这个局面 部分,以便对于第一列的每个可能值,有一个部分。
我们如何做到这一点?我的看法:
-- First, I'd like to define some type synonyms to make type signatures more
-- intuitive.
type Row = [String]
type Table = [Row]
-- It would be easier to deal with a row represented as a list, rather than a
-- tuple.
tupleToList :: (String, String, String, String) -> Row
tupleToList (a, b, c, d) = [a, b, c, d]
-- With some handy library functions, we can convert our input to Rows and
-- section it by teacher's name in one pass:
test' :: [Table]
test' = groupBy equalFirstColumn . map tupleToList $ test
where
equalFirstColumn = ((==) `on` head)
-- Now, we have to blank the repeating values. If the columns were lists, we
-- would do it like this:
blankRepetitions :: [String] -> [String]
blankRepetitions (x:xs) = x: replicate (length bef) "" ++ blankRepetitions aft
where (bef, aft) = span (== x) xs
blankRepetitions [ ] = [ ]
-- Luckily, there is a library function that can turn columns to rows and vice
-- versa. Let's use it.
test'' :: [Table]
test'' = map (transpose . map blankRepetitions . transpose) test'
-- Now we can turn our groups back into a single table. Why not add a row with
-- column captions as well.
test3 :: Table
test3 = ["Teacher", "Subject", "Class", "ExtraClass"] : concat test''
花点时间研究一下,看看它是否按预期工作。我怀疑地挥之不去 我处理消隐的方式有一些缺陷......
打印结果。
到目前为止,获取漂亮表格的最简单方法就是用空格填充每个单元格 这样每个单元格的宽度都相同:
pad :: Int -> String -> String
pad w s = " " ++ s ++ (replicate (w - length s) ' ')
但选择什么宽度?最长的细胞的宽度似乎是一个不错的选择。所以,我们可以去 那样:
columnize :: Table -> String
columnize xss = unlines . map concat . (map.map) (pad maxwidth) $ xss
where maxwidth = maximum . map length . concat $ xss
请注意map.map
如何处理列表列表的方式与单个map
处理的方式相同
一个简单的。
就是这样!看一下如何将一个复杂的问题转化为一个很容易的问题 较小的。