(defn find-index-route [x coll]
(letfn [(path-in [y]
(cond
(= y x) '()
(coll? y) (let [[failures [success & _]]
(->> y
(map path-in)
(split-with not))]
(when success (cons (count failures) success)))))]
(path-in coll)))
Examples:
(find-index-route :my-key '(1 2 :my-key)) ;=> [2]
=> (2)
(find-index-route :my-key '(1 2 "a" :my-key "b")) ;=> [3]
=> (3)
(find-index-route :my-key '(1 2 [:my-key] "c")) ;=> [2 0]
=> (2 0)
(find-index-route :my-key '(1 2 [3 [:my-key]])) ;=> [2 1 0]
=> (2 1 0)
(find-index-route :my-key '(1 2 [3 [[] :my-key]])) ;=> [2 1 1]
=> (2 1 1)
(find-index-route :my-key '(1 2 [3 [4 5 6 (:my-key)]])) ;=> [2 1 3 0]
=> (2 1 3 0)
(find-index-route :my-key '(1 2 [3 [[]]])) ;=> nil or []
=> nil
Thinking about performance
split-with , take-while drop-while, . , drop-while, , :
(defn counted-drop-while [pred coll]
(loop [takes 0, tail coll]
(if (and (seq tail) (pred (first tail)))
(recur (inc takes) (rest tail))
[takes tail])))
. find-index-route :
(defn find-index-route [x coll]
(letfn [(path-in [y]
(cond
(= y x) '()
(coll? y) (let [[fail-count [success & _]]
(->> y
(map path-in)
(counted-drop-while not))]
(when success (cons fail-count success)))))]
(path-in coll)))
... .