hi, I have just discovered specter and am a newbie, requesting some help - I have data which can have arbitrary depth and branches -
{:role0 {:clients {:a 1
:b 2}
:children {:role1 {:clients {:c 3}
:children {:role3 {:clients {:d 4}}}}
:role2 {:clients {:e 5
:f 6}}}}}
Each level can have :clients and :children keys. I want to select all the client values such that the above returns
[{:a 1} {:b 2} {:c 3} {:d 4} {:e 5} {:f 6}]
I have written the below snippet using specter but it returns the whole data ad a vector -
(def data {:role0 {:clients {:a 1
:b 2}
:children {:role1 {:clients {:c 3}
:children {:role3
{:clients {:d 4}}}}
:role2 {:clients {:e 5
:f 6}}}}})
(def TREE-VALUES
(sp/recursive-path [] p
(sp/if-path map?
[sp/ALL p]
sp/STAY)))
(sp/select TREE-VALUES data)
I wonder if you should see this as a two step process - one to get the maps second to split them into single vale maps.
true splitting could be done in second step, I am having trouble in extracting the values in the first place
I found this in the specter docs -
(def map-key-walker
(sp/recursive-path [akey]
p
[sp/ALL (sp/if-path [sp/FIRST #(= % akey)]
sp/LAST
[sp/LAST p])]))
Based on the example its suppose to return all instances of a key, however for my data it only returned {:a 1 :b 2}I have tried several options and like you am stuck. Hopefully @nathanmarz will be able to quickly give a solution. I do find quite a bit of my time writing Clojure is simply spent trying to work out things like this.
you can do it like this:
(def NODES
(recursive-path [] p
[MAP-VALS
(stay-then-continue
:children p)]))
(select [NODES :clients ALL (view (fn [[k v]] {k v}))] data)
;; => [{:a 1} {:b 2} {:c 3} {:d 4} {:e 5} {:f 6}]thanks @nathanmarz, thats neat.
I would love to know how you think through these problems to come up with such a neat solution.
for this one, I can see that as long as I can navigate to the root of every map containing :children and :clients, it's trivial to get to the desired data
and that from those locations I can navigate to all children maps recursively
so that's what NODES encodes
mentally I literally visualize paths as hopping around a data structure
Thank you that is really helpful
it's completely intuitive for me at this point, I think it gets easier with practice