是否有一个jQuery类型函数来解决遍历嵌套映射的问题?
例如,如果我有一个如下所示的配置:
(def fig
{:config
{:example
{:a "a"
:b "b"
:c "c"}
:more
{:a "a"
:b "b"
:c "c"}}})
我还没有找到一种使用assoc和dissoc来操作嵌套持久数据结构的好方法。但是,如果有一种jquery
样式的方式来操作地图,那么我可以编写如下代码:
(-> fig
($ [:config :example :a] #(str % "a"))
($ [:config :b] #(str % "b")))
Giving this output:
{:config
{:example
{:a "aa"
:b "bb"
:c "c"}
:more
{:a "a"
:b "bb"
:c "c"}}}
选择器之类的东西:
($ fig [:config :example :a])
;=> "a"
($ fig [:config :b])
;=> {[:config :example :b] "b",
; [:config :more :b] "b"}
所以从本质上讲,我正在寻找jayq
的实现来操作clojure对象而不是html doms。
提前致谢!
答案 0 :(得分:6)
update-in
是更新嵌套地图的绝佳功能。
user> (def data {:config
{:example {:a "a" :b "b" :c "c"}}
:more {:a "a" :b "b" :c "c"}})
user> (pprint (update-in data [:config :example] assoc :d 4))
{:config {:example {:a "a", :c "c", :b "b", :d 4}},
:more {:a "a", :c "c", :b "b"}}
assoc-in
可能会更接近你想要的东西
user> (pprint (assoc-in data [:config :example :d] 4))
{:config {:example {:a "a", :c "c", :b "b", :d 4}},
:more {:a "a", :c "c", :b "b"}}
为了在不更改它们的情况下读取值,您可以使用关键字在地图中查找自己的事实来编写比jquery表单更紧凑的形式
user> (-> data :config :example :a)
"a"
答案 1 :(得分:4)
首先,你应该看看Enlive。
否则:如果你想做jQuery所做的事情(当然非常简化) - 而不是只是调用update-in:
:选择:强>
(defn clj-query-select [obj path]
(if (empty? path)
(list obj)
(when (map? obj)
(apply concat
(remove nil?
(for [[key value] obj]
(clj-query-select
value
(if (= key (first path)) (rest path) path))))))))
致电:
(clj-query-select {:a {:b 1} :b 2} [:b])
它应该产生:
(1 2)
<强>更新/替换:强>
(defn clj-query-update [obj path fn]
(if (empty? path)
(fn obj)
(if (map? obj)
(into obj
(remove nil?
(for [[key value] obj]
(let [res (clj-query-update
value
(if (= key (first path)) (rest path) path)
fn)]
(when (not= res value) [key res])))))
obj)))
致电:
(clj-query-update {:c {:a {:b 1} :b 2}} [:c :b] #(* % 2))
它应该产生:
{:c {:a {:b 2} :b 4}}
我没有彻底测试它。