是否有更好的方式来交叉联合地图?

时间:2014-10-28 12:59:10

标签: haskell

最近我多次遇到这种模式。基本上它会处理asbs中也存在的所有键,并且不会触及其他键。

foo :: (a -> b -> a) -> Map a -> Map b -> Map a
foo f as bs = (Map.intersectionWith f as bs) `Map.union` (Map.difference as bs)

由于union的性质,这可以缩短为:

bar :: (a -> b -> a) -> Map a -> Map b -> Map a
bar f as bs = Map.intersectionWith f as bs `Map.union` as

但是这仍需要三次遍历(两次超过as一次超过bs)。我的直觉是应该有一种方法可以通过两次遍历来解决这个问题。

1 个答案:

答案 0 :(得分:6)

实际上它就在那里:Map.differenceWith做对了我想要的。这有点不直观,但基本上它需要asbs 的实际差异,而可以将交叉点中的值包含在结果集中。

因此这个

foo :: (a -> b -> a) -> Map a -> Map b -> Map a
foo f as bs = (Map.intersectionWith f as bs) `Map.union` (Map.difference as bs)

可以改写为

baz :: (a -> b -> a) -> Map a -> Map b -> Map a
baz f as bs = Map.differenceWith (\a b -> Just (f a b)) as bs

简单...抱歉浪费你的时间:)。