我想逐行打印三元组列表。该列表包含三元组,三元组的每个第一个元素应放在作为tirples的第二个和第三个元素给出的坐标中。网格从(0,0)坐标开始。 下面是一个2x2网格示例:
generateGrid [('a',0,0),('b',0,2),('c',1,1), ('d',2,2)]
-> a - b
- c -
- - d
我有一种生成此功能的方法,但我无法将所有内容都放在代码中。 我试图找到三元组中的最大数字,并按其递增的值创建网格。通过这种方式,我可以从(0,0)cooradinate开始。然后,我想查看所有三元组并将第一个元素放在相关坐标中。 我怎样才能采用这种方法?
以下是我的代码:
gridMax ((p1, p2, p3):xs) = max (maximum(secList ((p1, p2, p3):xs))) (maximum(thirdList ((p1, p2, p3):xs)))
secList [] = []
secList ((p1, p2, p3):xs) = [p2] ++ secList xs
thirdList [] = []
thirdList ((p1, p2, p3):xs) = [p3] ++ thirdList xs
这样我就找到了网格的最大值,这意味着我应该从(0,0)开始创建一个(max + 1)X(max + 1)网格。我无法获得剩下的代码。
答案 0 :(得分:1)
由于Haskell的懒惰,我们可以假设我们有一个无限网格,所以我们可以根据参数中逐个给出的坐标在这个网格上设置单元格,并在此过程中记录结果网格的大小。当我们完成时,我们可以从无限网格中获取结果网格。
以下是这个想法的实现:
setVal :: Int -> a -> [a] -> [a]
setVal idx val lst = h ++ (val : tail t)
where (h, t) = splitAt idx lst
setCell :: (Char, Int, Int) -> [[Char]] -> [[Char]]
setCell (c, x, y) grid = setVal x xl grid
where xl = setVal y c $ grid !! x
generateGrid :: [(Char, Int, Int)] -> [[Char]]
generateGrid cs = take (mx+1) $ map (take (my+1)) grid
where (mx, my, grid) = foldr step (0, 0, g) cs
g = repeat $ repeat '-'
step co@(c, x, y) (mx, my, g) =
let g' = setCell co g
mx' = max x mx
my' = max y my
in
(mx', my', g')
可以这样测试:
*Main> let cs = [('a',0,0),('b',0,2),('c',1,1), ('d',2,2)] :: [(Char, Int, Int)]
*Main> putStr $ unlines $ generateGrid cs
a-b
-c-
--d
答案 1 :(得分:0)
只是为了好玩,这里是Haskell One-Liner:
generateGrid :: [((Int, Int), Char)] -> String
generateGrid xs =
unlines $ map (map snd) $ groupBy ((==) `on` fst . fst) $ assocs $ accumArray (const id) '-' ((0,0), (maximum $ map (fst . fst) xs, maximum $ map (snd . fst) xs)) xs
让我们解码这里发生的事情:
generateGrid :: [((Int, Int), Char)] -> String
generateGrid xs =
unlines .
map (map snd) .
groupBy ((==) `on` fst . fst) .
assocs .
accumArray (const id)
'-'
((0,0), (maximum $ map (fst . fst) xs, maximum $ map (snd . fst) xs))
$ xs
我们要做的第一件事是使用accumArray :: (e -> a -> e) -> e -> (i, i) -> [(i, a)] -> Array i e
创建一个数组。它需要一个默认的'元素 - 这里有'-'
,原因很明显;一个组合函数,这里是const id
- 它只返回第二个元素,它将是从列表中提取的元素;范围,从(0,0)
开始,以最大值结束;最后,xs
输入列表,这是与值(Int, Int)
相关联的键Char
列表。
这一点的全部意义是"填写" ((x,y),'-')
的空格。 accumArray
是一种非常简单的方法。
然后我们使用assocs
从数组中取回一个列表。
下一个函数将获取关联列表并将它们分组到子列表中 - 每个子列表包含一行。
现在我们有一个行列表 - 我们不再对索引感兴趣,所以map (map snd)
摆脱了它们。最后,unlines
将行组合成一个由换行符分隔的单个字符串。