Функция типа 'jQuery' для манипулирования картами clojure
Существует ли функция типа jQuery для решения проблемы обхода вложенных карт?
например, если у меня есть конфигурация, которая выглядит следующим образом:
(def fig
{:config
{:example
{:a "a"
:b "b"
:c "c"}
:more
{:a "a"
:b "b"
:c "c"}}})
Я до сих пор не нашел отличный способ манипулировать вложенными постоянными структурами данных с помощью Assoc и Disoc. Однако, если бы был 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.
Заранее спасибо!
2 ответа
Прежде всего, вы должны проверить Enlive.
В противном случае: если вы хотите делать то, что делает jQuery (конечно, очень упрощенно), а не просто вызывать update:
Выбрать:
(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}}
Я не проверил это полностью, хотя.
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"