Home > Mobile >  Haskell - Merge two lists of tuples by first component
Haskell - Merge two lists of tuples by first component

Time:07-21

I have the following lists of tuples:

List 1:

[("key-1", Type1, Type2, Type3), ("key-2", Type1, Type2, Type3)]

List 2:

[("key-1", Type4), ("key-2", Type4)]

and I want to merge these tuples by its first component so that the following result is produced:

Result List:

[("key-1", Type1, Type2, Type3, Type4), ("key-2", Type1, Type2, Type3, Type4)]

In what way can I create the result list?

CodePudding user response:

How about using zipWith:

main = print $ merge list1 list2
-- [("key-1",0,True,"a string",'a'),("key-2",1,False,"another string",'b')]

merge :: [(a,b,c,d)] -> [(a,e)] -> [(a,b,c,d,e)]
merge = zipWith $ \(a,b,c,d) (_,e) -> (a,b,c,d,e)

list1 = [("key-1", 0, True, "a string"), ("key-2", 1, False, "another string")]
list2 = [("key-1", 'a'), ("key-2", 'b')]

CodePudding user response:

In general case I would go with converting to maps approach:

import Data.Map (Map)
import qualified Data.Map as Map

merge :: Ord a => [(a,b,c,d)] -> [(a,e)] -> [(a,b,c,d,e)]
merge left right = let
    mleft   = Map.fromList $ map (\(k, a,b,c) -> (k, (a,b,c))) left
    mright  = Map.fromList right
    mergeL (a, b, c, d) acc = case Map.lookup a mright of
        Nothing -> acc -- can't merge
        Just e  -> (a, b, c, d, e) : acc
    in foldr mergeL [] left

Note this will get rid of keys that are not present in both lists. In case you need to preserve those you can generate entry with some default values for Nothing case, add similarly looking mergeR and concatenate two foldr in result.

  • Related