diff --git a/.gitignore b/.gitignore index 91d15fb..9faeae1 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,4 @@ resources/public/ .store package-lock.json .cache +*.iml \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 4304757..8cc5658 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ ## Fixed +Varying key order in maps should produce a consistent diff (#47) + ## Changed # 2.9.202 (2023-06-09 / 35494a0) diff --git a/src/lambdaisland/deep_diff2/diff_impl.cljc b/src/lambdaisland/deep_diff2/diff_impl.cljc index e864f87..ce90472 100644 --- a/src/lambdaisland/deep_diff2/diff_impl.cljc +++ b/src/lambdaisland/deep_diff2/diff_impl.cljc @@ -1,5 +1,6 @@ (ns lambdaisland.deep-diff2.diff-impl (:require [clojure.data :as data] + [clojure.set :as set] [lambdaisland.clj-diff.core :as seq-diff])) (declare diff diff-similar) @@ -109,26 +110,22 @@ (remove #(contains? exp %) act))) (defn diff-map [exp act] - (first - (let [exp-ks (keys exp) - act-ks (keys act) - [del ins] (del+ins exp-ks act-ks)] - (reduce - (fn [[m idx] k] - [(cond-> m - (contains? del idx) - (assoc (->Deletion k) (get exp k)) - - (not (contains? del idx)) - (assoc k (diff (get exp k) (get act k))) - - (contains? ins idx) - (into (map (juxt ->Insertion (partial get act))) (get ins idx))) - (inc idx)]) - [(if (contains? ins -1) - (into {} (map (juxt ->Insertion (partial get act))) (get ins -1)) - {}) 0] - exp-ks)))) + (let [exp-ks (set (keys exp)) + act-ks (set (keys act))] + (reduce + (fn [m k] + (case [(contains? exp-ks k) (contains? act-ks k)] + [true false] + (assoc m (->Deletion k) (get exp k)) + [false true] + (assoc m (->Insertion k) (get act k)) + [true true] + (assoc m k (diff (get exp k) (get act k))) + ; `[false false]` will never occur because `k` necessarily + ; originated from at least one of the two sets + )) + {} + (set/union exp-ks act-ks)))) (defn primitive? [x] (or (number? x) (string? x) (boolean? x) (inst? x) (keyword? x) (symbol? x))) diff --git a/test/lambdaisland/deep_diff2/diff_test.cljc b/test/lambdaisland/deep_diff2/diff_test.cljc index 04c4f58..766546f 100644 --- a/test/lambdaisland/deep_diff2/diff_test.cljc +++ b/test/lambdaisland/deep_diff2/diff_test.cljc @@ -92,6 +92,15 @@ (is (= {:a [1 (diff/->Deletion 2) 3]} (diff/diff {:a [1 2 3]} {:a [1 3]})))) + (testing "map key order doesn't impact diff result" + (is (= {:name (diff/->Mismatch "Alyysa P Hacker" "Alyssa P Hacker"), :age 40} + + (diff/diff (array-map :name "Alyysa P Hacker" :age 40) + (array-map :age 40 :name "Alyssa P Hacker")) + + (diff/diff (array-map :age 40 :name "Alyysa P Hacker") + (array-map :age 40 :name "Alyssa P Hacker"))))) + (testing "records" (is (= {:a (diff/->Mismatch 1 2)} (diff/diff (map->ARecord {:a 1}) (map->ARecord {:a 2}))))