i wanted overwrite default value in relation specific values , stumbled upon behavior don't quite understand.
(clojure.set/join #{ {:a 1 :b nil :c "2"} {:a 2 :b "2" :c nil} {:a 3 :b 1 :c 5} } #{ {:a 1 :b 44} {:a 3 :b 11 :c 55} } {:a :a}) resolves #{{:a 3, :c 5, :b 1} {:c "2", :a 1, :b nil}}.
if flip arguments same result.
(clojure.set/join #{ {:a 1 :b 44} {:a 3 :b 11 :c 55} } #{ {:a 1 :b nil :c "2"} {:a 2 :b "2" :c nil} {:a 3 :b 1 :c 5} } {:a :a}) also resolves #{{:a 3, :c 5, :b 1} {:c "2", :a 1, :b nil}}.
what expected (at least first statement) #{{:a 3, :c 55, :b 11} {:c "2", :a 1, :b 44}}.
first question: why don't expect?
second question: why same result regardless of argument order?
just in case wants solution problem stated in beginning
( (fn [default, data, key] (->> default (map (fn [defaultentry] (merge defaultentry (->> data (filter (fn [dataentry] (= (key defaultentry) (key dataentry)))) first) ) )) ) ) #{ {:a 1 :b nil :c "2"} {:a 2 :b "2" :c nil} {:a 3 :b 1 :c 5} } #{ {:a 1 :b 44} {:a 3 :b 11 :c 55} } :a ) (warning: assumes key unique!)
from clojure.set/join code can see set fewer elements used index , set more elements reduced looking each element in index , keeping merged version each found item.
(defn join "when passed 2 rels, returns rel corresponding natural join. when passed additional keymap, joins on corresponding keys." ; 2-arity version removed brevity ([xrel yrel km] ;arbitrary key mapping (let [[r s k] (if (<= (count xrel) (count yrel)) [xrel yrel (map-invert km)] [yrel xrel km]) idx (index r (vals k))] (reduce (fn [ret x] (let [found (idx (rename-keys (select-keys x (keys k)) k))] (if found (reduce #(conj %1 (merge %2 x)) ret found) ret))) #{} s)))) that's why you'll same result (set/join b) or (set/join b a), except if both sets of same length, not case.
it explains why #{{:a 3, :c 5, :b 1} {:c "2", :a 1, :b nil}} instead of #{{:a 3, :c 55, :b 11} {:c "2", :a 1, :b 44}}: values in maps longer set take precedence on values shorter set when there's match.
Comments
Post a Comment