How to compare data structures in clojure and highlight differences
What I really searched for was difform. Using clojure.data/diff
is nice but does not work well in a unit test where larger structures are compared. Here is an example where data/diff
does not perform as well as difform in my opinion:
(defn example []
(let [data [{:foo 1} {:value [{:bar 2}]}]]
(diff data
[{:value [{:bar 2}]}])
(difform data
[{:value [{:bar 2}]}])))
;; => diff output
;; => [[{:foo 1} {:value [{:bar 2}]}] [{:value [{:bar 2}]}] nil]
;; => difform output
[{:
- foo 1} {:
value [{:bar 2}]}]
;; => nil
Take a look at clojure.data/diff: http://clojure.github.io/clojure/clojure.data-api.html#clojure.data/diff
Examples:
async-demo.core> (use 'clojure.data)
nil
async-demo.core> (diff {:a 2 :b 4} {:a 2})
({:b 4} nil {:a 2})
async-demo.core> (diff [1 2 3 4] [1 2 6 7])
[[nil nil 3 4] [nil nil 6 7] [1 2]]
async-demo.core> (diff #{"one" "two" "three"} #{"one" "fourty-four"})
[#{"two" "three"} #{"fourty-four"} #{"one"}]
Differ is a recent library that seems to do a nice job:
(def person-map {:name "Robin"
:age 25
:sex :male
:phone {:home 99999999
:work 12121212})
(def person-diff (differ/diff person-map {:name "Robin Heggelund Hansen"
:age 26
:phone {:home 99999999})
;; person-diff will now be [{:name "Robin Heggelund Hansen"
;; :age 26}
;; {:sex 0
;; :phone {:work 0}]
EDITED: fix Differ repo URL that change from gitlab to GitHub
You can also visually diff two data structures using the gui-diff library.
(gui-diff {:a 1} {:a 2})
will shell out to an OS-appropriate gui diffing program to diff the two, potentially very large, data structures.