Fork me on GitHub
#specter
<
2020-12-22
>
denik16:12:46

Is there a way to use specter to traverse a nested map and return the key paths where a predicate on the value returns true?

denik16:12:03

for example, if the predicate is string? and this is the nested map

{:a "foo" 
 :b {:c {:d "bar"}
     :e 42}}
it should return
[[:a]
 [:b :c :d]]

denik18:12:40

got it to work! the only part that’s missing now is to return :a and :x in a vector, like [[:a] [:x] [:b :c :d] [:b :f :y]]

(do
    (defn paths-till-pred [v-pred data]
      (let [walker (recursive-path [] p
                                   (if-path map?
                                            [ALL
                                             (if-path [LAST v-pred]
                                                      FIRST
                                                      [(collect-one FIRST) ALL p])]))]
        (select walker data)
        ))

    (paths-till-pred string? {:a "foo"
                             :x "foo"
                             :b {:c {:d "bar"}
                                 :e 42
                                 :f {:y "baz"}}}))
=> [:a :x [:b :c :d] [:b :f :y]]