12

次の問題の解決策を見つけることができません。

私が地図を持っているとしましょう:

(def defaults {
  :name    "John"
  :surname "Doe"
  :info    {:date-of-birth "01-01-1980"
            :registered    [{:type "newsletter" :name "breaking news" }]}
})

次に、同様の構造化されたマップを渡しますが、ベクトルを結合して残りのキーを上書きしたいと考えています。

(def new {
  :name    "Peter"
  :info    {:date-of-birth "11-01-1986"
            :registered    [{:type "alert" :name "mobile-alert" }]}
})

そして、私はこの結果が欲しいです:

 {:name    "Peter"
  :surname "Doe"
  :info    {:date-of-birth "11-01-1986"
            :registered    [{:type "newsletter" :name "breaking news" }
                            {:type "alert"      :name "mobile-alert" }]}}

次のような静的構文を使用して、これを簡単に行うことができます。

(reduce conj (get-in defaults [:info :registered]) (get-in new [:info :registered]))

(おそらくもっと良い方法があります...)しかし、次のプロパティを持つ動的関数をもっと望んでいました:

  1. 構造を知らなくても、両方のマップからすべてのキーを保持します
  2. 正しいマップの値でキーを更新します
  3. キーの val がconjベクトルの場合、右マップのベクトルを持つベクトル (もちろん適切なキーが存在する場合)

事前に助けてくれてありがとう:)

4

2 に答える 2

25

merge-with関数を必ず確認する必要があります。これは可能な実装です:

(defn deep-merge [a b]
  (merge-with (fn [x y]
                (cond (map? y) (deep-merge x y) 
                      (vector? y) (concat x y) 
                      :else y)) 
                 a b))
于 2013-06-26T18:54:20.697 に答える