Created
April 30, 2019 22:38
-
-
Save kvas-it/a765ed4a71b888d108b2e4e5ea10ede4 to your computer and use it in GitHub Desktop.
Find what changed between two data structures
This file contains 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
(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)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
cs
namespace isclojure.set