Skip to content

Instantly share code, notes, and snippets.

@kvas-it
Created April 30, 2019 22:38
Show Gist options
  • Save kvas-it/a765ed4a71b888d108b2e4e5ea10ede4 to your computer and use it in GitHub Desktop.
Save kvas-it/a765ed4a71b888d108b2e4e5ea10ede4 to your computer and use it in GitHub Desktop.
Find what changed between two data structures
(defn- prefix-paths
"Add a prefix to each of the paths in a sequence."
[pfx paths]
(map #(cons pfx %) paths))
(defn changed-paths
"Return a sequence of paths that differ between two nested data structures."
[a b]
(cond
; same item: no differences
(= a b)
()
; sequences: items only in one list + changed items
(and (sequential? a) (sequential? b))
(let [a-len (count a)
b-len (count b)
len-diff (if (> a-len b-len)
(range b-len a-len)
(range a-len b-len))
item-changes (map-indexed prefix-paths
(map changed-paths a b))]
(apply concat
(map list len-diff)
item-changes))
; maps: keys only in one map + changed keys
(and (map? a) (map? b))
(let [a-keys (set (keys a))
b-keys (set (keys b))
key-changes (map #(prefix-paths %
(changed-paths (% a) (% b)))
(cs/intersection a-keys b-keys))]
(apply concat
(map list (cs/difference a-keys b-keys))
(map list (cs/difference b-keys a-keys))
key-changes))
; this item is changed: empty path
:else
(list ())))
; team.xmod.evecs.core=> (changed-paths [1 1 {:a 5 :c [1 3 3]} 4] [1 2 {:a 5 :b 1 :c [1 2 3]}])
; ((3) (1) (2 :b) (2 :c 1))
@kvas-it
Copy link
Author

kvas-it commented Apr 30, 2019

cs namespace is clojure.set

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment