簡體   English   中英

clojure.set / join的意外選擇和合並行為

[英]The unexpected selection and merging behavior of clojure.set/join

我想用某些特定值覆蓋關系中的某些默認值,並偶然發現了一些我不太了解的行為。

(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})

解析為#{{:a 3, :c 5, :b 1} {:c "2", :a 1, :b nil}}

如果翻轉參數,我將得到相同的結果。

(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}) 

也解析為#{{:a 3, :c 5, :b 1} {:c "2", :a 1, :b nil}}

我所期望的(至少從第一句話開始)是#{{:a 3, :c 55, :b 11} {:c "2", :a 1, :b 44}}

第一個問題:為什么我沒有得到我所期望的?

第二個問題:為什么無論參數順序如何都得到相同的結果?


萬一有人想讓我解決我開頭提到的問題

(
  (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
)

(警告:假定key是唯一的!)

clojure.set / join代碼中,我們可以看到具有較少元素的集合用作索引,而通過查找索引中的每個元素並為每個找到的項保留合並版本,可以減少具有更多元素的集合。

(defn join
  "When passed 2 rels, returns the rel corresponding to the natural
  join. When passed an additional keymap, joins on the corresponding
  keys."
  ; 2-arity version removed for 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))))

這就是為什么使用(set/join ab)(set/join ba)會得到相同結果的原因,除非兩組的長度相同(這不是您的情況)。

它還說明了為什么獲得#{{:a 3, :c 5, :b 1} {:c "2", :a 1, :b nil}}而不是#{{:a 3, :c 55, :b 11} {:c "2", :a 1, :b 44}} :存在匹配時,較長集合中的映射值優先於較短集合中的值。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM