Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 如何取消列表展平_Haskell - Fatal编程技术网

Haskell 如何取消列表展平

Haskell 如何取消列表展平,haskell,Haskell,我可以轻松地展平嵌套数据结构,但双重操作似乎非常困难(至少对我来说) 给定类型列表[(a,b,c)],如何创建嵌套结构,即 unflatten :: (Ord a, Ord b) => [(a,b,c)] -> [(a, [(b, [c])])] 这样每个a只发生一次,同样的(a,b) 我不太清楚为什么我要这么做,因为双重操作非常简单 flatten :: [(a, [(b, [c])])] -> [(a,b,c)] flatten xs = [(a,b,c) | (a,bc

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

给定类型列表
[(a,b,c)]
,如何创建嵌套结构,即

unflatten :: (Ord a, Ord b) => [(a,b,c)] -> [(a, [(b, [c])])]
这样每个
a
只发生一次,同样的
(a,b)

我不太清楚为什么我要这么做,因为双重操作非常简单

flatten :: [(a, [(b, [c])])] -> [(a,b,c)]
flatten xs = [(a,b,c) | (a,bcs) <- xs, (b,cs) <- bcs, c<-cs]
flatten::[(a,[(b,[c])]->[(a,b,c)]

展平xs=[(a,b,c)|(a,bcs)就我个人而言,我会将数据放入嵌套的映射中。之后,您总是可以将其再次拉出到嵌套的关联列表中

首先,将每个项目转换为一个(小)嵌套映射,列表中有一个元素
[c]

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])])]
实际上,您可能不会
plattolists
,因为嵌套映射是更有用的结构

顺便说一句,如果
Map
具有“正确”的幺半群结构,那么
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]

就我个人而言,我会将这些数据放入一个嵌套的映射中。之后,您总是可以将其再次拉入嵌套的关联列表中

首先,将每个项目转换为一个(小)嵌套映射,列表中有一个元素
[c]

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])])]
实际上,您可能不会
plattolists
,因为嵌套映射是更有用的结构

顺便说一句,如果
Map
具有“正确”的幺半群结构,那么
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]

按照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))
印刷品

[ ( "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" ] )
        ]
      )
    ]
  )
]

按照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))
印刷品

[ ( "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" ] )
        ]
      )
    ]
  )
]

如果您对a、b、c没有限制,这是不可能的,但您应该看看
groupBy
您是否可以编写或提供更简单的分组函数,即
[(a、b)]->[(a、[b])]
?@epsilonhalbe我添加了约束。不过我认为我不需要对c进行约束。如果你没有约束-对a,b,c这是不可能的,但你应该看看
groupBy
你能写一个或你有一个更简单的groupBy函数吗,即
[(a,b)]->[(a,[b])]
?@epsilonhalbe我添加了约束。不过我认为我不需要c上的约束。