This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2017-10-11
Channels
- # beginners (57)
- # boot (9)
- # clara (9)
- # cljs-dev (12)
- # clojure (98)
- # clojure-boston (1)
- # clojure-dusseldorf (12)
- # clojure-france (1)
- # clojure-greece (1)
- # clojure-spec (41)
- # clojure-uk (86)
- # clojurescript (60)
- # code-art (2)
- # data-science (5)
- # datomic (5)
- # duct (1)
- # fulcro (14)
- # graphql (2)
- # lein-figwheel (4)
- # luminus (1)
- # midje (1)
- # off-topic (19)
- # om (10)
- # onyx (13)
- # pedestal (5)
- # portkey (59)
- # re-frame (31)
- # reagent (1)
- # ring (14)
- # ring-swagger (1)
- # rum (5)
- # shadow-cljs (90)
- # spacemacs (5)
- # specter (47)
- # sql (9)
- # uncomplicate (95)
- # vim (32)
I’m starting to get a feel for recursive-path
now, but I don’t see how I can solve my problem with it.
I want to pluck all the parents of a particular map based on a predicate for that map.
The way I see it, I’ll either have to start the search from the leaves of my tree or remove branches as it goes.
The latter would require that I keep track of my tree with some local-state, so it doesn’t seem idiomatic to specter?
This current solution will select the correct maps, but if I try to collect the previous result, that will happen for “bar” as well
@hkjels not entitely clear on what you're trying to do. Are you just trying to remove the children of all nodes matching a certain name?
@nathanmarz I’m trying to retrieve all the parent nodes of nodes where the predicate is true and leave out all the children
@hkjels so in this case you want to navigate to the parents of nodes with name "qux"?
looks like this:
(def data
{:name "foo"
:children
[{:name "bar"
:children []}
{:name "baz"
:children
[{:name "qux"
:children
[{:name "NO!"
:children
[]}]}]}
{:name "hello"
:children
[{:name "world"
:children
[{:name "qux"
:children
[{:name "NO!"
:children
[]}]}]}]}]})
(def NODES
(recursive-path [] p
(continue-then-stay :children ALL p)))
(defn nodes-with-child [name]
(path NODES (selected? :children ALL :name (pred= name)))
)
(select (nodes-with-child "qux") data)
easiest way to do a recursive navigation is first make a path that navigates to every node, then do whatever filtering you need on top of that
Nice tip! There’s still the issue where children of the selected node is in the structure
if you want the results without children then specify that in your selection
(select [(nodes-with-child "qux") (transformed :children (constantly NONE))] data)
I want to cherry-pick a set of values from different parts of a nested structure. Is that a reasonable thing to try to do with Specter?
I currently use get-in
and map over the keywords to get to each value. It works fine, but what is the principle behind doing that with specter?
In this sample dataset https://pastebin.com/MgtqLCXg
if you want to get all the summaries, it's (select [(keypath "issues") ALL (keypath "fields" "summary")] data)
I would like to pull multiple values, i.e. from issues/id, issues/key, issues/fields/summary, issues/fields/project/name
I'm not sure all those selects make sense in a single navigator do they?
how do you want the results structured?
I'm essentially trying to flatten the JSON data into CSV.
And cherry-pick just the values I need.
(select [(keypath "issues") ALL (collect-one (keypath "id")) (keypath "fields") (collect-one (keypath "summary")) (keypath "project" "name")] data)
that will get everything you need as a vector in that order
Ok, so drill down to the end element, but collect the values as you go?
if you're doing a lot of navigation by string keys, it may be worth creating an implicit navigator for strings as is done for keywords https://github.com/nathanmarz/specter/blob/master/src/clj/com/rpl/specter.cljc#L1161
then you can write (select ["issues" ALL (collect-one "id") ...
That part is ok, the string keys are turned into keywords using Cheshire when it parses
Regarding using collect...
I've just assumed collect-one
was only applicable when doing a transform. I didn't realise it would just contain the final elements!
yep, that's the only behavior that makes sense for select
codepath
Good stuff. Thank you, Nathan.
okay, I think I've found an interesting data structure for learning; koan 4 will be about writing transformations to facilitate a space-shooter game. this makes the examples like this easier to read (transform [ALL (collect-one :velocity) #(:enemy? %) :y] (fn [velocity current-y] (* velocity current-y)) entities)
this transformation obviously takes all the entity maps and updates every enemy's y coordinate by its velocity
that can process about 5k maps in sub-miliseconds (caveat: i'm using time
as my micro-benchmark tool)
@gdeer81 cool, that sounds nice and tangible
differences in decisions about how you want to manipulate the game objects easily illustrate subtle differences in navigations
@nathanmarz: Perhaps what you are thinking of is using re-seq? (re-seq #"." "abc") ("a" "b" "c")
(re-seq #"abc+" "abc") ("abc")
@michaelwfogleman yea, that looks right
ok cool
going to try and poke at the transform