简体   繁体   中英

Haskell - Merge two lists of tuples by first component

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?

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')]

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.

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM