Created
February 6, 2021 03:28
-
-
Save ichramm/86cd13c8b062256e2aaeed0d4c58e94a to your computer and use it in GitHub Desktop.
Compute common factor of multiple maps in Clojure
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;; manually | |
(defn compute-common-factor | |
[maps] | |
(if (empty? (rest maps)) | |
;; only one | |
(first maps) | |
(let [head (first maps) | |
maps (rest maps)] | |
(letfn [(reducer [path obj] | |
(reduce-kv (fn [m k v] | |
(let [[v set?] (if (map? v) | |
;; walk recursively | |
(let [v (reducer (conj path k) v)] | |
[v (not-empty v)]) | |
;; return v only if it is the same in all other maps | |
(when (->> maps | |
(map #(get-in % (conj path k))) | |
(remove #(contains? #{v} %)) | |
empty?) | |
[v true]))] | |
(if set? | |
(assoc m k v) | |
m))) | |
{} | |
obj))] | |
(reducer [] head))))) | |
;; using clojure.data/diff | |
;; Problem: Also works on vectors, therefore {:a [1 2]} vs {:a [1 2 3 4]} returns {:a [1 2]} | |
(defn compute-common-factor | |
[maps] | |
(loop [head (first maps) | |
remaining (rest maps)] | |
(if (empty? remaining) | |
head | |
(recur (last (clojure.data/diff head (first remaining))) | |
(rest remaining))))) | |
;; workaround: | |
(extend-protocol clojure.data/Diff | |
java.util.List | |
(diff-similar [a b] | |
(when (= a b) [nil nil a] [a b nil]))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment