This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2024-01-21
Channels
- # beginners (29)
- # calva (4)
- # clerk (10)
- # clojure (23)
- # clojure-doc (10)
- # clojure-europe (2)
- # clojure-norway (5)
- # clojure-poland (1)
- # clojuredesign-podcast (3)
- # data-science (1)
- # datomic (3)
- # emacs (38)
- # fulcro (4)
- # humbleui (8)
- # hyperfiddle (36)
- # introduce-yourself (4)
- # off-topic (10)
- # portal (14)
- # reitit (6)
- # specter (6)
I'm wondering if there is a more idiomatic way to accomplish the following transformation:
I have a vector of maps that each contain a vector of children
:
(def a-structure [{:children [{:a 1 :b 2} {:a 3 :b 4}] :something "a"}
{:children [{:a 4 :b 5} {:a 6 :b 10}] :something "b"}])
I want to transform the parent maps, and also filter and transform each of the child maps.
I came up with the following, where I do the filter and transform of children in two separate paths:
(sp/multi-transform
[sp/ALL (sp/multi-path
[(sp/terminal (fn [thing-with-children]
{:new-thing 1
:something-renamed (:something thing-with-children)
:children (:children thing-with-children)}))] ; apply transform to top-level object
[:children (sp/filterer [(sp/must :a) (sp/pred<= 1)]) (sp/terminal sp/NONE)] ; remove duds
[:children
sp/ALL
(sp/terminal (fn [child] {:a-renamed (:a child) :b-renamed (:b child)}))])] ; apply transform to each non-filtered child
a-structure)
Ignoring the fact that I'm just renaming keys, how can I make this transformation better?
I feel like the second path replacing filtered children with NONE
can't be the right way, but I can't figure out how to merge it with the last path, that actually transforms the unfiltered children.I tried inlining the filter:
(sp/multi-transform
[sp/ALL (sp/multi-path
[(sp/terminal (fn [thing-with-children]
{:new-thing 1
:something-renamed (:something thing-with-children)
:children (:children thing-with-children)}))] ; apply transform to top-level object
[:children
(sp/filterer [(sp/must :a) (sp/pred> 1)]) ; remove duds
sp/ALL
(sp/terminal (fn [child] {:a-renamed (:a child) :b-renamed (:b child)}))])] ; apply transform to each non-filtered child
a-structure)
But the :children
vector still contains the "filtered" item, because the first path includes :children in the top-level result
[{:new-thing 1,
:something-renamed "a",
:children [{:a 1, :b 2} {:a-renamed 3, :b-renamed 4}]}
{:new-thing 1,
:something-renamed "c",
:children [{:a-renamed 4, :b-renamed 5} {:a-renamed 6, :b-renamed 10}]}]
(notice the first child in the first result is not-transformed)map-key
is the navigator to use for renaming keys
Thanks! What do you think about
[:children (sp/filterer [(sp/must :a) (sp/pred<= 1)]) (sp/terminal sp/NONE)]
It seems like "select things to filter, replace them with NONE so they are omitted", which feels redundantyou need terminal-val
there
[:children ALL (sp/selected? (sp/must :a) (sp/pred<= 1)) (sp/terminal-val sp/NONE)]
is more performant
1