Skip to content

Commit 41d3153

Browse files
committed
Clean up and rework minimize implementation
1 parent 5793228 commit 41d3153

File tree

9 files changed

+155
-70
lines changed

9 files changed

+155
-70
lines changed

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
## Added
44

55
- Enable print tests in babashka
6-
- Add namespace `lambdaisland.deep-diff2.manipulate` ns with `remove-unchanged` API
6+
- Add a `lambdaisland.deep-diff2/minimize` function, which removes any items
7+
that haven't changed from the diff.
78

89
## Fixed
910

README.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,21 @@ For fine grained control you can create a custom Puget printer, and supply it to
8888

8989
For more advanced uses like incorporating diffs into your own Fipp documents, see `lambdaisland.deep-diff2.printer/format-doc`, `lambdaisland.deep-diff2.printer/print-doc`.
9090

91+
### Minimizing
92+
93+
If you are only interested in the changes, and not in any values that haven't
94+
changed, then you can use `ddiff/minimize` to return a more compact diff.
95+
96+
This is especially useful for potentially large nested data structures, for
97+
example a JSON response coming from a web service.
98+
99+
```clj
100+
(-> (ddiff/diff {:a "apple" :b "pear"} {:a "apple" :b "banana"})
101+
ddiff/minimize
102+
ddiff/pretty-print)
103+
;; {:b -"pear" +"banana"}
104+
```
105+
91106
### Print handlers for custom or built-in types
92107

93108
In recent versions deep-diff2 initializes its internal copy of Puget with

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@
44
"dependencies": {
55
"react": "^16.13.1",
66
"react-dom": "^16.13.1",
7-
"ws": "^8.11.0"
7+
"ws": "^8.13.0"
88
}
99
}

repl_sessions/poke.clj

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
(ns repl-sessions.poke
2+
(:require [lambdaisland.deep-diff2 :as ddiff]))
3+
4+
(seq #{{:foo 1M} {:bar 2}}) ;; => ({:foo 1M} {:bar 2})
5+
(seq #{{:foo 1} {:bar 2}}) ;; => ({:bar 2} {:foo 1})
6+
7+
(def d1 {{:foo 1M} {:bar 2}})
8+
(def d2 {{:foo 1} {:bar 2}})
9+
(ddiff/pretty-print (ddiff/diff d1 d2))
10+
;; #{+{:foo 1} -{:foo 1M} {:bar 2}}
11+
12+
(def d1 #{{:foo 1M}})
13+
(def d2 #{{:foo 1}})
14+
(ddiff/pretty-print (ddiff/diff d1 d2))
15+
16+
(-> (ddiff/diff {:a "apple" :b "pear"} {:a "apple" :b "banana"})
17+
ddiff/minimize
18+
ddiff/pretty-print)
19+
;; {:b -"pear" +"banana"}
20+
21+
;; {:b -2 +3}
22+
23+
[#{1.1197369622161879e-14 1.3019822841584656e-21 0.6875
24+
#uuid "a907a7fe-d2eb-482d-b1cc-3acfc12daf55"
25+
-30
26+
:X/*!1:3
27+
:u7*A/p?2IG5d*!Nl
28+
:**d7ws
29+
"ý"
30+
"ÔB*àñS�¬ÚûV¡ç�¯±·á£H�
31+
�û?'V$ëY;CL�k-oOV"
32+
!U-h_C*A7/x0_n1
33+
A-*wn./o_?4w18-!
34+
"ìêܼà4�^¤mÐðkt�ê1_ò�· À�4\n@J\"2�9)cd-\t®"
35+
y3W-2
36+
#uuid "6d507164-f8b9-401d-8c44-d6b0e310c248"
37+
"M"
38+
:cy7-3
39+
:w4/R.-s?9V5
40+
#uuid "1bcb00c9-88b9-4eae-9fea-60600dfaefa0"
41+
-20
42+
#uuid "269ab6f9-f19d-4c9d-a0cb-51150e52e9f7"
43+
-235024979
44+
:O:m_9.9+A/N+usPa6.HA*G
45+
228944.657438457
46+
:x/w?
47+
:__+o+sut9!t/?0l
48+
"�â��«"
49+
false
50+
#uuid "b6295f83-8176-47b5-946e-466f74226629"
51+
e3zQ!E*5
52+
:T5rb
53+
:++y:2
54+
-7364
55+
zG/ex23
56+
"¡"
57+
-4318364480
58+
:D+?2?!/Hrc!jA7z_2
59+
:z-I/!8Uq+d?
60+
-0.5588235294117647
61+
-0.5925925925925926
62+
-0.8108108108108109}]

src/lambdaisland/deep_diff2.cljc

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
(ns lambdaisland.deep-diff2
2-
(:require [lambdaisland.deep-diff2.diff-impl :as diff-impl]
3-
[lambdaisland.deep-diff2.printer-impl :as printer-impl]))
2+
(:require
3+
[lambdaisland.deep-diff2.diff-impl :as diff-impl]
4+
[lambdaisland.deep-diff2.printer-impl :as printer-impl]
5+
[lambdaisland.deep-diff2.minimize-impl :as minimize]))
46

57
(defn diff
68
"Compare two values recursively.
@@ -41,3 +43,8 @@
4143
(-> diff
4244
(printer-impl/format-doc printer)
4345
(printer-impl/print-doc printer))))
46+
47+
(defn minimize
48+
"Return a minimal diff, removing any values that haven't changed."
49+
[diff]
50+
(minimize/minimize diff))

src/lambdaisland/deep_diff2/manipulate.cljc

Lines changed: 0 additions & 48 deletions
This file was deleted.
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
(ns lambdaisland.deep-diff2.minimize-impl
2+
"Provide API for manipulate the diff structure data "
3+
(:require [clojure.walk :refer [postwalk]]
4+
#?(:clj [lambdaisland.deep-diff2.diff-impl]
5+
:cljs [lambdaisland.deep-diff2.diff-impl :refer [Mismatch Deletion Insertion]]))
6+
#?(:clj (:import [lambdaisland.deep_diff2.diff_impl Mismatch Deletion Insertion])))
7+
8+
(defn diff-item?
9+
"Checks if x is a Mismatch, Deletion, or Insertion"
10+
[x]
11+
(or (instance? Mismatch x)
12+
(instance? Deletion x)
13+
(instance? Insertion x)))
14+
15+
(defn has-diff-item?
16+
"Checks if there are any diff items in x or sub-tree of x"
17+
[x]
18+
(or (diff-item? x)
19+
(and (map? x) (some #(or (has-diff-item? (key %))
20+
(has-diff-item? (val %))) x))
21+
(and (coll? x) (some has-diff-item? x))))
22+
23+
(defn minimize
24+
"Postwalk diff, removing values that are unchanged"
25+
[diff]
26+
(let [y (postwalk
27+
(fn [x]
28+
(cond
29+
(map-entry? x)
30+
;; Either k or v of a map-entry contains/is? diff-item,
31+
;; keep the map-entry. Otherwise, remove it.
32+
(when (or (has-diff-item? (key x))
33+
(has-diff-item? (val x)))
34+
x)
35+
36+
(map? x)
37+
x
38+
39+
(coll? x)
40+
(into (empty x) (filter has-diff-item?) x)
41+
42+
:else
43+
x))
44+
diff)]
45+
(cond
46+
(coll? y) y
47+
:else nil)))
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
1-
(ns lambdaisland.deep-diff2.manipulate-test
1+
(ns lambdaisland.deep-diff2.minimize-test
22
(:require [clojure.test :refer [deftest testing is are]]
33
[lambdaisland.deep-diff2.diff-test :as diff-test]
44
[clojure.test.check.clojure-test :refer [defspec]]
55
[clojure.test.check.generators :as gen]
66
[clojure.test.check.properties :as prop]
77
[lambdaisland.deep-diff2.diff-impl :as diff]
8-
[lambdaisland.deep-diff2.manipulate :as manipulate]
98
[lambdaisland.deep-diff2 :as ddiff]))
109

1110
(deftest basic-strip-test
12-
(testing "diff without remove-unchanged"
11+
(testing "diff without minimize"
1312
(let [x {:a 1 :b 2 :d {:e 1} :g [:e [:k 14 :g 15]]}
1413
y {:a 1 :c 3 :d {:e 15} :g [:e [:k 14 :g 15]]}]
1514
(is (= (ddiff/diff x y)
@@ -18,62 +17,62 @@
1817
:d {:e (diff/->Mismatch 1 15)}
1918
:g [:e [:k 14 :g 15]]
2019
(diff/->Insertion :c) 3}))))
21-
(testing "diff with remove-unchanged"
20+
(testing "diff with minimize"
2221
(let [x {:a 1 :b 2 :d {:e 1} :g [:e [:k 14 :g 15]]}
2322
y {:a 1 :c 3 :d {:e 15} :g [:e [:k 14 :g 15]]}]
24-
(is (= (manipulate/remove-unchanged (ddiff/diff x y))
23+
(is (= (ddiff/minimize (ddiff/diff x y))
2524
{(diff/->Deletion :b) 2
2625
:d {:e (diff/->Mismatch 1 15)}
2726
(diff/->Insertion :c) 3})))))
2827

29-
(deftest remove-unchanged-on-diff-test
28+
(deftest minimize-on-diff-test
3029
(testing "diffing atoms"
3130
(testing "when different"
32-
(is (= (manipulate/remove-unchanged
31+
(is (= (ddiff/minimize
3332
(ddiff/diff :a :b))
3433
(diff/->Mismatch :a :b))))
3534

3635
(testing "when equal"
37-
(is (= (manipulate/remove-unchanged
36+
(is (= (ddiff/minimize
3837
(ddiff/diff :a :a))
3938
nil))))
4039

4140
(testing "diffing collections"
4241
(testing "when different collection types"
43-
(is (= (manipulate/remove-unchanged
42+
(is (= (ddiff/minimize
4443
(ddiff/diff [:a :b] #{:a :b}))
4544
(diff/->Mismatch [:a :b] #{:a :b}))))
4645

4746
(testing "when equal with clojure set"
48-
(is (= (manipulate/remove-unchanged
47+
(is (= (ddiff/minimize
4948
(ddiff/diff #{:a :b} #{:a :b}))
5049
#{})))
5150

5251
(testing "when different with clojure set"
53-
(is (= (manipulate/remove-unchanged
52+
(is (= (ddiff/minimize
5453
(ddiff/diff #{:a :b :c} #{:a :b :d}))
5554
#{(diff/->Insertion :d) (diff/->Deletion :c)})))
5655

5756
(testing "when equal with clojure vector"
58-
(is (= (manipulate/remove-unchanged
57+
(is (= (ddiff/minimize
5958
(ddiff/diff [:a :b] [:a :b]))
6059
[])))
6160

6261
(testing "when equal with clojure hashmap"
63-
(is (= (manipulate/remove-unchanged
62+
(is (= (ddiff/minimize
6463
(ddiff/diff {:a 1} {:a 1}))
6564
{})))
6665

6766
(testing "when equal with clojure nesting vector"
68-
(is (= (manipulate/remove-unchanged
67+
(is (= (ddiff/minimize
6968
(ddiff/diff [:a [:b :c :d]] [:a [:b :c :d]]))
7069
[])))))
7170

72-
;; "diff itself and remove-unchanged yields empty"
71+
;; "diff itself and minimize yields empty"
7372
(defspec diff-itself 100
7473
(prop/for-all
7574
[x diff-test/gen-any-except-NaN]
7675
(if (coll? x)
77-
(= (manipulate/remove-unchanged (ddiff/diff x x))
76+
(= (ddiff/minimize (ddiff/diff x x))
7877
(empty x))
79-
(nil? (manipulate/remove-unchanged (ddiff/diff x x))))))
78+
(nil? (ddiff/minimize (ddiff/diff x x))))))

tests.edn

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
#kaocha/v1
22
{:tests [{:id :clj}
33
{:id :cljs
4-
:type :kaocha.type/cljs}]}
4+
:type :kaocha.type/cljs}]
5+
:kaocha/bindings {kaocha.stacktrace/*stacktrace-filters* []}
6+
}

0 commit comments

Comments
 (0)