使用clojure的两个哈希映射的交集

Kam*_*kid 1 clojure

我是Clojure的新手.我的问题是如何获得两个哈希映射的交集,例如

(def map-1 {"a" 2, "b" 1, "c" 4, "d" 3})
(def map-2 {"a" 3, "b" 6, "e" 5})
Run Code Online (Sandbox Code Playgroud)

当我们定义两个映射时,预期的结果将是{"a" 3, "b" 6},它是在具有相交键和具有键的最大值的映射中.

不知怎的,我想出了一个解决方案并实现了它,但它的工作部分正确.

基本思想是找到其中项目数量最少的地图,将其用作参考.对于参考地图中的每个项目,检查其他地图是否包含它.如果它包含,则将键放入输出映射及其最大值(使用(max num1 num2))

以下是我的示例代码:

(defn max-intersect [map1 map2]
  (let [smaller-map (if (< (count map1) (count map2))
                      map1
                      map2)
        longer-map (if (= smaller-map map1)
                     map2
                     map1)]
        (loop [output {}
               reference-map smaller-map]
          (if (empty? reference-map)
            output
            (recur (let [[item-key item-val] (first smaller-map)]
                     (when (contains? longer-map item-key)
                       (assoc output item-key (max item-val (get longer-map item-key)))))
                   (rest reference-map))))))
Run Code Online (Sandbox Code Playgroud)

这是我的repl结果:

test-intersect.core=> (def map1 {"a" 2, "b" 1, "c" 4, "d" 3})
#'test-intersect.core/map1
test-intersect.core=> (def map2 {"a" 3, "b" 6, "e" 5})
#'test-intersect.core/map2
test-intersect.core=> (max-intersect map1 map2)
{"a" 3}
Run Code Online (Sandbox Code Playgroud)

这看起来很复杂,我也在等待任何有效的解决方案.

非常感谢!

Tay*_*ood 8

这可以通过merge-with使用max合并功能来完成:

(def map-1 {"a" 2, "b" 1, "c" 4, "d" 3})
(def map-2 {"a" 3, "b" 6, "e" 5})
(merge-with max map-1 map-2)
=> {"a" 3, "b" 6, "c" 4, "d" 3, "e" 5}
Run Code Online (Sandbox Code Playgroud)

merge-with就像merge但它允许您传递一个函数来在两个映射中出现一个键时选择合并的值.

要仅包含两个地图中显示的键,您可以使用select-keys两个地图键的集合交集:

(select-keys (merge-with max map-1 map-2)
             (clojure.set/intersection
               (set (keys map-1))
               (set (keys map-2))))
Run Code Online (Sandbox Code Playgroud)