举例说明:
(def nest1 {:a {:b {:c "foo"}}})
(def nest2 {:d {:e "bar"}})
如果我想在任意级别上联合这些巢,我可以明确地这样做:
(conj (-> nest1 :a :b) (-> nest2 :d)) ; yields {:e "bar", :c "foo"}
(conj (-> nest1 :a) (-> nest2 :d)) ; yields {:e "bar", :b {:c "foo"}}
但是如果我想创建一个接受nest1和nest2的“深度”作为参数的函数呢?
; Does not work, but shows what I am trying to do
(defn join-nests-by-paths [nest1-path nest2-path]
(conj (-> nest1 nest1-path) (-> nest2 nest2-path))
我可能会试着这样称呼它:
; Does not work
(join-nests-by-paths '(:a :b) '(:d))
这不起作用。我不能简单地将每个“路径”作为列表传递给函数(或者我可以,但需要在函数中以不同方式使用它)。
有什么想法? TIA ... 肖恩
答案 0 :(得分:5)
使用get-in:
(defn join-by-paths [path1 path2]
(conj (get-in nest1 path1) (get-in nest2 path2)))
user> (join-by-paths [:a :b] [:d])
{:e "bar", :c "foo"}
user> (join-by-paths [:a] [:d])
{:e "bar", :b {:c "foo"}}
您的版本实际上是这样做的:
user> (macroexpand '(-> nest1 (:a :b)))
(:a nest1 :b)
如你所说,不起作用。
get-in
有朋友assoc-in
和update-in
,全部用于处理嵌套的地图地图。在clojure.conrtrib中有一个dissoc-in
。
(在Clojure中,当您传递连续的事物组时,使用向量而不是引用列表更为惯用。)