我可以轻松地展平嵌套数据结构,但双重操作似乎非常困难(至少对我而言)。
给定类型ContentPlaceHolder
的列表,如何创建嵌套结构,即
[(a,b,c)]
这样每个unflatten :: (Ord a, Ord b) => [(a,b,c)] -> [(a, [(b, [c])])]
只出现一次,同样只出现a
我不太清楚为什么我在努力解决这个问题,因为双重操作非常简单
(a,b)
更新
根据EricR的建议,我编写了一个功能,它可以实现一个不平坦的功能,但我仍在努力扩展它
flatten :: [(a, [(b, [c])])] -> [(a,b,c)]
flatten xs = [(a,b,c) | (a,bcs) <- xs, (b,cs) <- bcs, c<-cs]
答案 0 :(得分:5)
我个人将这些数据放入嵌套地图中。您可以随后将其再次拉出到嵌套关联列表中。
首先将每个项目转换为(小)嵌套地图,其中包含列表[c]
中的1个元素:
import qualified Data.Map as M
import Data.List
triplesToMaps :: [(a,b,c)] -> [M.Map a (M.Map b [c])]
triplesToMaps = map (\(a,b,c) -> M.singleton a (M.singleton b [c]))
然后使用unionWith
combineMaps :: (Ord a, Ord b) => [M.Map a (M.Map b [c])] -> M.Map a (M.Map b [c])
combineMaps = foldl' (M.unionWith (M.unionWith (++))) M.empty
然后,如果您愿意,请将其带回列表:
flattenToLists :: M.Map a (M.Map b [c]) -> [(a,[(b,[c])])]
flattenToLists = M.assocs . (M.map M.assocs)
示例:
> flattenToLists . combineMaps . triplesToMaps $ [(1,2,3),(1,2,4),(1,3,5),(2,6,8)]
[(1,[(2,[3,4]),(3,[5])]),(2,[(6,[8])])]
在实践中,您可能不会flattenToLists
,因为嵌套地图是更有用的结构。
顺便提一下,如果Map
拥有&#34;权利&#34; Monoid结构然后M.unionWith (M.unionWith (++))
只是mappend
,整个事情可能是foldMap (\(a,b,c) -> M.singleton a (M.singleton b [c]))
。
[编辑:在问题中添加了双重]
哦,回到[(a,b,c)]
我想到了两种方法。列表理解与您的一样,但使用assocs
:
flatten :: M.Map a (M.Map b [c]) -> [(a,b,c)]
flatten m = [(a,b,c) | (a,bcs) <- M.assocs m, (b,cs) <- M.assocs bcs, c <- cs]
或使用foldMap的版本:
flatten' :: M.Map a (M.Map b [c]) -> [(a,b,c)]
flatten' = M.foldMapWithKey (\a -> M.foldMapWithKey (\b -> foldMap (\c -> [(a,b,c)])))
答案 1 :(得分:0)
根据ErikR的建议,出现了一种模式,将其扩展为更长和更长的元组。
-- construct some raw material
l a i = map ((a ++) . show) [1..i]
l4 = [(a,b,c,d) | d<-l "d" 3, c <- l "c" 3, b<-l "b" 3, a<-l "a" 2 ]
grp2 :: Ord a => [(a,b)] -> [(a,[b])]
grp2 xs = do
a <- (nub . sort . map fst) xs
let bs = [b' | (a',b') <- xs, a'==a]
return (a,bs)
grp3 :: (Ord a, Ord b) => [(a,b,c)] -> [(a,[(b,[c])])]
grp3 ys = do
(a, bcs) <- grp2 (map split3 ys)
return (a, grp2 bcs)
where
split3 (a,b,c) = (a,(b,c))
grp4 :: (Ord a, Ord b, Ord c) => [(a,b,c,d)] -> [(a,[(b,[(c,[d])])])]
grp4 zs = do
(a, bcds) <- grp2 (map split4 zs)
return (a, grp3 bcds)
where
split4 (a,b,c,d) = (a,(b,c,d))
现在
*Main> pp $ grp4 l4
打印
[ ( "a1"
, [ ( "b1"
, [ ( "c1" , [ "d1" , "d2" , "d3" ] )
, ( "c2" , [ "d1" , "d2" , "d3" ] )
, ( "c3" , [ "d1" , "d2" , "d3" ] )
]
)
, ( "b2"
, [ ( "c1" , [ "d1" , "d2" , "d3" ] )
, ( "c2" , [ "d1" , "d2" , "d3" ] )
, ( "c3" , [ "d1" , "d2" , "d3" ] )
]
)
, ( "b3"
, [ ( "c1" , [ "d1" , "d2" , "d3" ] )
, ( "c2" , [ "d1" , "d2" , "d3" ] )
, ( "c3" , [ "d1" , "d2" , "d3" ] )
]
)
]
)
, ( "a2"
, [ ( "b1"
, [ ( "c1" , [ "d1" , "d2" , "d3" ] )
, ( "c2" , [ "d1" , "d2" , "d3" ] )
, ( "c3" , [ "d1" , "d2" , "d3" ] )
]
)
, ( "b2"
, [ ( "c1" , [ "d1" , "d2" , "d3" ] )
, ( "c2" , [ "d1" , "d2" , "d3" ] )
, ( "c3" , [ "d1" , "d2" , "d3" ] )
]
)
, ( "b3"
, [ ( "c1" , [ "d1" , "d2" , "d3" ] )
, ( "c2" , [ "d1" , "d2" , "d3" ] )
, ( "c3" , [ "d1" , "d2" , "d3" ] )
]
)
]
)
]