I have a simple question, i am new to Haskell and trying to learn a lot. How can i concatenate for example
[( (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]]
I want to concatenate the lists that have first element of the pair equal. I tried
map concat list
map (\t -> (filter (==).first) list ) list
but the first one doesn't work and the second one gives an error. Any ideas?
using a couple functions from Data.List
and Data.Function.on
this becomes:
import Data.List (sortBy, groupBy)
import Data.Function (on)
sortByFirst :: Ord a => [(a, b)] -> [(a, b)]
sortByFirst = sortBy (compare `on` fst)
the groupBy
functions expect that the data is sorted, so we must first sort by each inner tuple (ie sort by (a, b)
in ((a, b), [x,y,z])
)
groupByFirst :: Eq a => [(a, b)] -> [[(a, b)]]
groupByFirst = groupBy ((==) `on` fst)
then we use groupBy
to group the resulting list of tuples into lists of lists of tuples, where each inner list shares the same first element.
squishByFirst :: (Eq a, Ord a) => [(a, b)] -> [[b]]
squishByFirst = (map . concatMap) snd . groupByFirst . sortByFirst
then we use some fancy mapping over snd
to roll into each inner list, pull out the second element (the list), combine them together, and give back the result. This is equivalent to:
squishByFirst xs =
let grouped = groupByFirst . sortByFirst $ xs
in [concat [ys | (_, ys) <- g] | g <- grouped]
You can also implement this as a fold over Map.insertWith
import Data.Map (elems, empty, insertWith)
squishByFirst :: Ord k => [(k, [v])] -> [[v]]
squishByFirst = elems . mkMap
where
mkMap = foldr (uncurry (insertWith (++))) empty
or for any Monoid:
squishByFirst :: (Ord k, Monoid vs) => [(k, vs)] -> [vs]
squishByFirst = elems . mkMap
where
mkMap = foldr (uncurry (insertWith mappend)) empty
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.