Skip to content

Commit 4d92566

Browse files
authored
Merge pull request #48 from RutledgePaulV/fix-map-diffing-under-variable-key-order
varying key order in maps should produce consistent diffs
2 parents 5a3c15a + f9e37b2 commit 4d92566

File tree

4 files changed

+29
-20
lines changed

4 files changed

+29
-20
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,4 @@ resources/public/
2020
.store
2121
package-lock.json
2222
.cache
23+
*.iml

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
## Fixed
66

7+
Varying key order in maps should produce a consistent diff (#47)
8+
79
## Changed
810

911
# 2.9.202 (2023-06-09 / 35494a0)

src/lambdaisland/deep_diff2/diff_impl.cljc

Lines changed: 17 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
(ns lambdaisland.deep-diff2.diff-impl
22
(:require [clojure.data :as data]
3+
[clojure.set :as set]
34
[lambdaisland.clj-diff.core :as seq-diff]))
45

56
(declare diff diff-similar)
@@ -109,26 +110,22 @@
109110
(remove #(contains? exp %) act)))
110111

111112
(defn diff-map [exp act]
112-
(first
113-
(let [exp-ks (keys exp)
114-
act-ks (keys act)
115-
[del ins] (del+ins exp-ks act-ks)]
116-
(reduce
117-
(fn [[m idx] k]
118-
[(cond-> m
119-
(contains? del idx)
120-
(assoc (->Deletion k) (get exp k))
121-
122-
(not (contains? del idx))
123-
(assoc k (diff (get exp k) (get act k)))
124-
125-
(contains? ins idx)
126-
(into (map (juxt ->Insertion (partial get act))) (get ins idx)))
127-
(inc idx)])
128-
[(if (contains? ins -1)
129-
(into {} (map (juxt ->Insertion (partial get act))) (get ins -1))
130-
{}) 0]
131-
exp-ks))))
113+
(let [exp-ks (set (keys exp))
114+
act-ks (set (keys act))]
115+
(reduce
116+
(fn [m k]
117+
(case [(contains? exp-ks k) (contains? act-ks k)]
118+
[true false]
119+
(assoc m (->Deletion k) (get exp k))
120+
[false true]
121+
(assoc m (->Insertion k) (get act k))
122+
[true true]
123+
(assoc m k (diff (get exp k) (get act k)))
124+
; `[false false]` will never occur because `k` necessarily
125+
; originated from at least one of the two sets
126+
))
127+
{}
128+
(set/union exp-ks act-ks))))
132129

133130
(defn primitive? [x]
134131
(or (number? x) (string? x) (boolean? x) (inst? x) (keyword? x) (symbol? x)))

test/lambdaisland/deep_diff2/diff_test.cljc

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,15 @@
9292
(is (= {:a [1 (diff/->Deletion 2) 3]}
9393
(diff/diff {:a [1 2 3]} {:a [1 3]}))))
9494

95+
(testing "map key order doesn't impact diff result"
96+
(is (= {:name (diff/->Mismatch "Alyysa P Hacker" "Alyssa P Hacker"), :age 40}
97+
98+
(diff/diff (array-map :name "Alyysa P Hacker" :age 40)
99+
(array-map :age 40 :name "Alyssa P Hacker"))
100+
101+
(diff/diff (array-map :age 40 :name "Alyysa P Hacker")
102+
(array-map :age 40 :name "Alyssa P Hacker")))))
103+
95104
(testing "records"
96105
(is (= {:a (diff/->Mismatch 1 2)}
97106
(diff/diff (map->ARecord {:a 1}) (map->ARecord {:a 2}))))

0 commit comments

Comments
 (0)