specter

Latest version: 1.1.3
pepe 2018-06-24T14:22:44.000109Z

Hello, I have this data:

[{:id 0}
 {:id 1}
 {:id 2 :parent-id 1 :val 1}
 {:id 3 :parent-id 1 :val 1}
 {:id 4 :parent-id 2 :val 2}
 {:id 5 :parent-id 3 :val 2}
 {:id 6 :parent-id 3 :val 2}
 {:id 7 :parent-id 0 :val 100}
 {:id 8 :parent-id 7 :val 200}
 {:id 9 :parent-id 6 :val 3}]
And I would like to traverse all the :val for :id = 1 and all its descendants. Is it possible with specter?

nathanmarz 2018-06-24T15:29:21.000036Z

@pepe yes, you can do it with zippers

pepe 2018-06-24T15:30:03.000017Z

Is it that I have to first compose the tree first then?

nathanmarz 2018-06-24T15:32:21.000004Z

no

nathanmarz 2018-06-24T15:32:23.000057Z

one sec I'll show you

1
nathanmarz 2018-06-24T15:37:33.000102Z

@pepe

(use 'com.rpl.specter)
(require '[com.rpl.specter.zipper :as z])

(def data
  [{:id 0}
   {:id 1}
   {:id 2 :parent-id 1 :val 1}
   {:id 3 :parent-id 1 :val 1}
   {:id 4 :parent-id 2 :val 2}
   {:id 5 :parent-id 3 :val 2}
   {:id 6 :parent-id 3 :val 2}
   {:id 7 :parent-id 0 :val 100}
   {:id 8 :parent-id 7 :val 200}
   {:id 9 :parent-id 6 :val 3}])

(def TO-GRAPH (path z/VECTOR-ZIP z/DOWN))
(defn to-node [id]
  (z/find-first #(= (:id %) id))
  )

(def CHILDREN
  (path
    (collect-one z/NODE :id)
    z/LEFTMOST
    z/NEXT-WALK
    (collect-one z/NODE :parent-id)
    (collected? [id1 id2] (= id1 id2))
    DISPENSE
    ))

(def DESCENDANTS (recursive-path [] p (stay-then-continue CHILDREN p)))

(select [TO-GRAPH (to-node 1) DESCENDANTS z/NODE (must :val)] data)

nathanmarz 2018-06-24T15:37:47.000061Z

that said, it's a really bad representation for a tree

pepe 2018-06-24T15:40:31.000013Z

You mean my data? Yeah, some legacy stuff. I will try it and report back. Thank you very much for help!

pepe 2018-06-24T16:07:02.000108Z

On some bigger trees I am getting Maximum call stack size exceeded in CLJS. Indeed this representation is bad 😞

pepe 2018-06-24T16:36:23.000127Z

The thing as always, is that those data I am receiving from API. The call stack is exceeded in the recursive-path

nathanmarz 2018-06-24T18:55:59.000079Z

@pepe you can do better with custom navigators rather than zippers

nathanmarz 2018-06-24T18:57:03.000030Z

see defnav

nathanmarz 2018-06-24T18:58:03.000002Z

navigate to pair of [list-of-nodes index], and then make custom CHILDREN navigator that does the search for indices that are direct children of currently navigated index