如何在嵌套的hashmap中合并?

时间:2014-03-26 12:59:50

标签: clojure

我有一个嵌套的hashmap,其结构类似于以下内容:

(def pathmap {:order {:genus {:species {:cat2 "data", :cat1 "data"}}}})

我需要的是像assoc-in这样的函数,它允许我将新的键值对添加到最里面的嵌套映射,而不是简单地替换已存在的那些。例如:

(my-assoc-merge pathmap [:order :genus :species] {:cat3 "data"})
;=> {:order {:genus {:species {:cat3 "data" :cat2 "data", :cat1 "data"}}}}

我想我可以通过稍微改变assoc-in函数来使用merge-with和union来轻松地做到这一点:

(defn my-assoc-merge
  [m [k & ks] v]
  (if ks
    (assoc m k (my-assoc-merge (get m k) ks v))
    (assoc m k (merge-with clojure.set/union (get m k '{}) v))))

不幸的是,这给了我错误“CompilerException java.lang.UnsupportedOperationException:此类型不支持count:关键字,编译:(core.clj:34:12)”。我哪里错了?

1 个答案:

答案 0 :(得分:5)

实际上,assoc-in已经创建了一个新密钥(如果它不存在)。用法如下:

(def pathmap {:order {:genus {:species {:cat2 "data", :cat1 "data"}}}})

(assoc-in pathmap [:order :genus :species :cat3] "data")
;=> {:order {:genus {:species {:cat2 "data", :cat3 "data", :cat1 "data"}}}}

如果您想合并新地图,请将update-inmerge

一起使用
(update-in pathmap [:order :genus :species] merge {:cat3 "data"})
;=> {:order {:genus {:species {:cat2 "data", :cat3 "data", :cat1 "data"}}}}

my-assoc-merge的问题是union,它适用于集合。将merge-with更改为merge并删除union