2014-10-28 91 views
2

最近我遇到过这种模式几次。基本上它处理as中的所有密钥,这些密钥也存在于bs中,并且不会触及其他密钥。有没有更好的方式相交然后联合地图?

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)。我的直觉是,只有两次遍历才能解决这个问题。

+2

也许很一般['mergeWithKey'(HTTP: //hackage.haskell.org/package/containers-0.5.5.1/docs/Data-Map-Lazy.html#v:mergeWithKey)函数可以用于此。 – chi 2014-10-28 13:13:26

+0

我会尝试在chi链接处给出的myIntersectionWithKey示例中替换第一个*(const empty)* by * id *。 – 2014-10-28 13:30:48

回答

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 

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

相关问题