Fork me on GitHub
#specter
<
2017-08-20
>
michaelwfogleman17:08:56

There was recently a very interesting question on Stack Overflow - no one has written a Specter-based solution yet... I am trying to write one.

nathanmarz17:08:42

@michaelwfogleman I'll take a closer look later, but you basically want to use recursive-path, collect-one, and INDEXED-VALS

nathanmarz18:08:44

@michaelwfogleman looks like this:

(defn find-index-route [v data]
  (let [p (recursive-path [] p
            (if-path sequential?
              [INDEXED-VALS
               (if-path [LAST (pred= v)]
                 FIRST
                 [(collect-one FIRST) LAST p]
                 )]))]
    (let [ret (select-first p data)]
      (if (vector? ret) ret [ret])
      )))

souenzzo21:08:43

Mine, w/o specter but works on maps and find "all" routes

(defn find-index-route
  "find all routes to some value"
  ([k x] (find-index-route k x []))
  ([k x p]
   (cond
     (= k x) [p]
     (coll? x) (->> (if (map? x) x (vec x))
                    (reduce-kv (fn [acc i v]
                                 (into (vec (find-index-route k v (conj p i))) acc)) []))
     :else nil)))

nathanmarz07:08:46

@souenzzo a slight modification makes the specter version work for maps as well:

(defn find-index-route [v data]
  (let [p (recursive-path [] p
            [(if-path map? ALL INDEXED-VALS)
             (if-path [LAST (pred= v)]
               FIRST
               [(collect-one FIRST) LAST coll? p]
               )])]
    (let [ret (select-first p data)]
      (if (or (nil? ret) (vector? ret)) ret [ret])
      )))

nathanmarz07:08:46

@souenzzo a slight modification makes the specter version work for maps as well:

(defn find-index-route [v data]
  (let [p (recursive-path [] p
            [(if-path map? ALL INDEXED-VALS)
             (if-path [LAST (pred= v)]
               FIRST
               [(collect-one FIRST) LAST coll? p]
               )])]
    (let [ret (select-first p data)]
      (if (or (nil? ret) (vector? ret)) ret [ret])
      )))