开发者

How to add fields to a map in Clojure?

开发者 https://www.devze.com 2023-02-22 11:11 出处:网络
I have a map like this: {:a 1 :b 20} : and I want to make sure that certain fields are not missing from the map:

I have a map like this:

{:a 1 :b 20}

: and I want to make sure that certain fields are not missing from the map:

(:a :b :c :d )

: Is there a function to merge the two, something like :

(merge-missing-keys {:a 1 :b 20} (:a :b :c :d ))

: which can produce :

{:a 1 :b 20 :c nil :d nil}

?

Update:

With some pointers from the answers I found that this can be done like this:

(defn merge-missing-keys [
                           a-set 
                           some-keys
                         ]
          (merge-with 
              开发者_JAVA百科           #(or %1 %2) 
                         a-set  
                         (into {} (map (fn[x] {x nil}) some-keys))))

(merge-missing-keys {:a 1 :b 20} '(:a :b :c :d :e ))


You should use merge-with:

Returns a map that consists of the rest of the maps conj-ed onto the first. If a key occurs in more than one map, the mapping(s) from the latter (left-to-right) will be combined with the mapping in the result by calling (f val-in-result val-in-latter).

So the following will merge all maps with one actual value selected from the maps or nil.

(merge-with #(or %1 %2) 
            {:a 1 :b 2} 
            {:a nil :b nil :c nil :d nil})
; -> {:d nil :c nil :b 2 :a 1}

This will probably be enough for you to build your implementation.


You can always just merge into your default array as follows:

(merge
  {:a nil :b nil :c nil :d nil} ; defaults
  {:a 1 :b 20})                 ; current values

=> {:a 1, :b 20, :c nil, :d nil}


A riff on @mikera's answer, to make it work when you don't have the keys available as literals:

(let [keys [:a :b :c :d]]
 (merge (zipmap keys (repeat nil))
        {:a 1 :b 20}))
0

精彩评论

暂无评论...
验证码 换一张
取 消