TheReshi
TheReshi

Reputation: 81

Haskell pair of a number and list

I have a problem. I have a task that can't solve on my own. Here is the deal:

extPair :: Eq a => [(a,b)] -> [(a,[b])]    

If I want to call this with:

extPair [(3,"pear"),(3,"fog"),(4,"dog"),(4,"x"),(3,"y")]

Should give the following result:

[(3, ["pear", "fog"]), (4, ["dog", "x"]), (3, ["y"])] :: [(Integer, [[Char]])]

All I know now is:

extPair [] = []
extPair (x:xs)
 | length (x:xs) >= 2 && fst x == fst (head xs) = [(fst x, [snd x, snd (head xs)])] ++ extPair (drop 1 xs)
 | otherwise = [(fst x, [snd x])]

This works fine for the example, but it doesn't work on the following, and I don't know how to make it, so I ask Your help. I would like to add as many pairs as I want like:

extPair [(3,"pear"),(3,"fog"),(3,"dark"),(3,"etc"), ... ,(4,"dog"),(4,"x"),(3,"y"),(3,"z")]

So the result should be:

    [(3, ["pear", "fog", "dark", "etc", "...", "...", ...]), (4, ["dog", "x"]), (3, ["y", "z"])] :: [(Integer, [[Char]])]

Upvotes: 0

Views: 526

Answers (2)

bmk
bmk

Reputation: 1568

Yet another solution using the foldr function:

extPair :: Eq a => [(a,b)] -> [(a,[b])]
extPair = foldr f []
  where
    f (key, elem) [] = [(key, [elem])]
    f (key1, elem) l@((key2, elems):xs)
      | key1 == key2 = (key2,elem:elems):xs
      | otherwise    = (key1,[elem]):l

Upvotes: 3

chi
chi

Reputation: 116174

You can start by pre-processing the list with groupBy:

> import Data.List
> import Data.Function
> groupBy ((==) `on` fst) [(3,"pear"),(3,"fog"),(4,"dog"),(4,"x"),(3,"y")]
[[(3,"pear"),(3,"fog")],[(4,"dog"),(4,"x")],[(3,"y")]]

From there, use map f for a suitable f.


If you instead want to write your own code, consider recursion:

extPair ((n,s):xs) = ???
   where ys = extPair xs

the logic here would something like: if ys starts with (n,zs), then prepend s to zs, otherwise prepend (n,[s]) to ys.

Upvotes: 1

Related Questions