压缩两个HashMap

时间:2019-02-16 17:05:59

标签: haskell

假设我有两个HashMap:

echo -e "listen\nsilent" | ./anagram > /dev/null; echo $?

我想要某种import Data.HashMap.Strict m1 :: HashMap Char Int m2 :: HashMap Char Int ??? :: (v1 -> v2 -> v3) -> HashMap k v1 -> HashMap k v2 -> HashMap k v3 -- or even ??? :: (k -> v1 -> v2 -> v3) -> HashMap k v1 -> HashMap k v2 -> HashMap k v3 遍历这些地图,其中:

  1. 如果一个密钥存在于一个映射中,但另一个映射中不存在,则将其替换为默认密钥(“最长的zip”
  2. 结果类型可以与原始类型不同

这将intersectionWithKey的签名与语义更接近unionWithKey的匹配。

一个具体示例:对于一个简单的应用zip且默认值为0的简单情况,我可以这样做

(,)

这引发了一个问题:通常有一种干净的方法吗?

2 个答案:

答案 0 :(得分:1)

通常:

  1. 合并两个地图以获取所有键的列表
  2. 定义一个新函数,该函数在给定键的情况下使用lookupDefault 从每个地图中依次获取适当的值(默认值或实数) 计算新地图的值
  3. 对该键起作用的映射,并根据结果创建一个新的哈希映射。

zipMap :: (v1 -> v2 -> v3) -- Combining function
       -> v1               -- default value for keys unique to the second map
       -> v2               -- default value for keys unique to the first map
       -> HashMap k v1
       -> HashMap k v2
       -> HashMap k v3
zipMap f d1 d2 m1 m2 = let allKeys = keys (union m1 m2)
                           f' k = (k, f (lookupDefault d1 k m1) (lookupDefault d2 k m2))
                       in fromList $ map f' allKeys

答案 1 :(得分:1)

these程序包提供了These数据类型,有点像Either,但是在出现两种情况时都具有一个额外的构造函数。

>

该包还定义了用于在数据结构上“带填充压缩”的类型类。特别是Align类型类,它有一个HashMap实例。

例如,使用0压缩两个地图以查找丢失的条目:

import Data.These
import Data.Align

padWithZeros :: (Align f, Num a, Num b) => f a -> f b -> f (a, b)
padWithZeros = alignWith (fromThese 0 0)

还有Data.Align.IndexedData.Align.Keyed,它们使压缩功能可以访问密钥。

these的一个缺点是依赖项占用量很大。