列表列表haskell

时间:2018-04-19 21:14:29

标签: list haskell

我有一个简单的问题,我是Haskell的新手,并试图学习很多东西。 我如何连接例如

 [( (0,1) , [1,2,3]) , ((1,2) , [7,8,9]) ,((0,1) , [4,5,6]) ] to [[1,2,3,4,5,6] , [7,8,9]]

我想连接具有该对的第一个元素相等的列表。 我试过了

 map concat list 

 map (\t -> (filter (==).first) list ) list 

但第一个不起作用,第二个发出错误。 有什么想法吗?

1 个答案:

答案 0 :(得分:2)

使用Data.ListData.Function.on中的几个函数,这将成为:

import Data.List     (sortBy, groupBy)
import Data.Function (on)

sortByFirst :: Ord a => [(a, b)] -> [(a, b)]
sortByFirst = sortBy (compare `on` fst)

groupBy函数期望数据被排序,因此我们必须首先按每个内部元组排序(即在(a, b)中按((a, b), [x,y,z])排序)

groupByFirst :: Eq a => [(a, b)] -> [[(a, b)]]
groupByFirst = groupBy ((==) `on` fst)

然后我们使用groupBy将结果的元组列表分组到元组列表的列表中,其中每个内部列表共享相同的第一个元素。

squishByFirst :: (Eq a, Ord a) => [(a, b)] -> [[b]]
squishByFirst = (map . concatMap) snd . groupByFirst . sortByFirst

然后我们使用snd上的一些花哨映射来滚动到每个内部列表,拉出第二个元素(列表),将它们组合在一起,然后返回结果。这相当于:

squishByFirst xs =
  let grouped = groupByFirst . sortByFirst $ xs
  in  [concat [ys | (_, ys) <- g] | g <- grouped]

您也可以将其作为Map.insertWith

的折叠来实现
import Data.Map (elems, empty, insertWith)

squishByFirst :: Ord k => [(k, [v])] -> [[v]]
squishByFirst = elems . mkMap
  where
  mkMap = foldr (uncurry (insertWith (++))) empty

或任何Monoid:

squishByFirst :: (Ord k, Monoid vs) => [(k, vs)] -> [vs]
squishByFirst = elems . mkMap
  where
  mkMap = foldr (uncurry (insertWith mappend)) empty