Search code examples
clojurespecter

Using specter to transform values that match a key


I'm sorry if this has been answered elsewhere, but I can't seem to find an example that matches the pattern of what I'm looking for. I also may not yet understand recursive specter paths fully.

If I have the data (explicitly with the nested vector):

{:a "1" :b "2" :c [ {:a "3" :b "4"} {:a "5" :b "6"} ]}

And I'd like to apply the keyword function to all values with the key :a to result in:

{:a :1 :b "2" :c [ {:a :3 :b "4"} {:a :5 :b "6"} ]}

Finally, I'd like it to be recursive to an arbitrary depth, and handle the vector case as well.

I've read https://github.com/nathanmarz/specter/wiki/Using-Specter-Recursively , but I must be missing something critical.

Thanks to anyone pointing me in the right direction!


Solution

  • (use '[com.rpl.specter])
    (let [input          {:a "1" :b "2" :c [{:a "3" :b "4"} {:a "5" :b "6"}]}
          desired-output {:a :1 :b "2" :c [{:a :3 :b "4"} {:a :5 :b "6"}]}
          FIND-KEYS      (recursive-path [] p (cond-path map? (continue-then-stay [MAP-VALS p])
                                                         vector? [ALL p]
                                                         STAY))]
    
        (clojure.test/is
            (= (transform [FIND-KEYS (must :a)] keyword input)
               desired-output)))