如何取消展平列表

时间:2015-11-11 16:17:30

标签: haskell

我可以轻松地展平嵌套数据结构,但双重操作似乎非常困难(至少对我而言)。

给定类型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]

2 个答案:

答案 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" ] )
        ]
      )
    ]
  )
]