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.