如果我有2个Haskell地图,例如:
[("a",1),
("b",2),
("c",1)]
和
[("a",1)]
如何以这样的方式编写函数:
[("a",2),("b",2),("c",1)]
到目前为止,我只能编写基本案例,但这就是全部。
答案 0 :(得分:12)
来自Data.Map
的unionWith
怎么样?
以下是在两个地图m1
和m2
上使用它的GHCi会话示例,其中包含密钥“a”:
Prelude> import qualified Data.Map as Map
Prelude Data.Map> let m1 = Map.fromList [('a', 1)]
Prelude Data.Map> let m2 = Map.fromList [('a', 2), ('b', 10)]
Prelude Data.Map> Map.unionWith (+) m1 m2
fromList [('a',3),('b',10)]
如果你想定义自己的功能来包装所有这些:
mergeMap :: (Ord k, Num a) => Map.Map k a -> Map.Map k a -> Map.Map k a
mergeMap = Map.unionWith (+)
与
相同mergeMap a b = Map.unionWith (+) a b
甚至
a `mergeMap` b = Map.unionWith (+) a b
如果你愿意,你也可以让GHC推断mapUnion
的类型,但它会推断出相同的类型。
注意:在现实生活中,请务必在懒惰和严格的地图之间做出正确的选择,因此在Data.Map.Strict.unionWith
和Data.Map.Lazy.unionWith
之间做出正确的选择。
答案 1 :(得分:2)
Map
的替代方案是sort
。此版本假定每个键在每个列表中只出现一次。如果情况并非如此,你可以修复它,但Map
方法会开始看起来更具吸引力。
combine op xs ys = cs op (s xs) (s ys)
where
s = sortBy (compare `on` fst)
cs _ [] qs = qs
cs _ ps [] = ps
cs op pss@(p@(pk,pv):ps) qss@(q@(qk,qv):qs) =
case compare pk qk of
LT -> p : cs op ps qss
GT -> q : cs op pss qs
EQ -> (pk, pv `op` qv) : cs op ps qs