Ответ 1
Я не уверен, что самый эффективный способ сделать это, но вот несколько вещей, которые могут быть полезны:
-
Основное ожидание поведения из текста вопроса невозможно: если
a
иb
являются такими картами, чтоb
содержит хотя бы один ключ, отсутствующий вa
,(merge b <sth>)
не может быть равнымa
. -
Если вы закончите работу с interop-решением, но в какой-то момент вам нужно вернуться к
PersistentHashMap
, всегда(clojure.lang.PersistentHashMap/create (doto (java.util.HashMap.) (.put :foo 1) (.put :bar 2))) ; => {:foo 1 :bar 2}
-
Если вам нужно передать набор ключей Clojure на Java-метод, вы можете использовать
(.keySet {:foo 1 :bar 2}) ; => #< [:foo, :bar]>
-
Если все задействованные ключи гарантированно
Comparable
, это может быть использовано для эффективного вычисленияdifference
на картах со многими ключами (сортировка и слияние). Для неограниченных ключей это, конечно, не-go и для небольших карт, это может реально повредить производительность. -
Хорошо иметь версию, написанную в Clojure, если только для установки ожидаемого результата базовой линии. Вот один из них: (обновлено)
(defn map-difference [m1 m2] (loop [m (transient {}) ks (concat (keys m1) (keys m2))] (if-let [k (first ks)] (let [e1 (find m1 k) e2 (find m2 k)] (cond (and e1 e2 (not= (e1 1) (e2 1))) (recur (assoc! m k (e1 1)) (next ks)) (not e1) (recur (assoc! m k (e2 1)) (next ks)) (not e2) (recur (assoc! m k (e1 1)) (next ks)) :else (recur m (next ks)))) (persistent! m))))
Я думаю, что просто делать
(concat (keys m1) (keys m2))
и, возможно, дублировать некоторую работу, скорее всего, будет более эффективно большую часть времени, чем проверка данного ключа в "другой карте" тоже на каждом шагу.
Чтобы завершить ответ, здесь очень простая идея на основе набора с хорошим свойством, что он говорит, что он делает - если я неправильно понял спецификацию, это должно быть легко видно здесь.: -)
(defn map-difference [m1 m2]
(let [ks1 (set (keys m1))
ks2 (set (keys m2))
ks1-ks2 (set/difference ks1 ks2)
ks2-ks1 (set/difference ks2 ks1)
ks1*ks2 (set/intersection ks1 ks2)]
(merge (select-keys m1 ks1-ks2)
(select-keys m2 ks2-ks1)
(select-keys m1
(remove (fn [k] (= (m1 k) (m2 k)))
ks1*ks2)))))