我是Clojure的新手。我的问题是如何获得两个哈希映射的交集,例如
(def map-1 {"a" 2, "b" 1, "c" 4, "d" 3})
(def map-2 {"a" 3, "b" 6, "e" 5})
在我们定义两张地图时,预期结果为{"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))))))
这是我的复制结果:
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}
看起来很复杂,我也在等待任何有效的解决方案。
非常感谢!
答案 0 :(得分:8)
使用max
作为合并功能{/ 3}}即可完成此操作:
(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}
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))))
答案 1 :(得分:1)
(require '[clojure.set :refer [intersection]])
(defn merge-with-max-intersecting
[m1 m2]
(let [intersecting (intersection (set (keys m1))
(set (keys m2)))]
(merge-with max
(select-keys m1 intersecting)
(select-keys m2 intersecting))))
(merge-with-max-intersecting {"a" 2, "b" 1, "c" 4, "d" 3}
{"a" 3, "b" 6, "e" 5})
;;=> {"a" 3, "b" 6}
答案 2 :(得分:1)
你也可以像这样一次通过:
(defn merge-maps [m1 m2]
(reduce-kv (fn [acc k v]
(if (contains? m1 k)
(assoc acc k (max v (m1 k)))
acc))
{}
m2))
user> (merge-maps map-1 map-2)
;;=> {"a" 3, "b" 6}