Suppose I have a nested structure, something like this:
{:data1
{:categories [
{:name "abc" :id 234 :desc "whatever"}
{:name "def" :id 456 :desc "nothing"}]
}
:data2 {...}
:data3 {...}
}
And I need to transform the key names in the maps. I can transform the top level keys like this:
(rename-keys mymap {:data1 :d1})
But I'm not sure how to rename keys nested more deeply in the data structure (say I want to rename the :desc field to :description).
I'm pretty sure that zippers are the answer but can't quite figure out how to do it, or if there's a more straightforward way.
postwalk
is a pretty heavy sledgehammer in general, although it looks from your original question like you might need it. In many cases, you can perform updates in a nested structure with update-in
:
user> (let [m {:foo {:deep {:bar 1 :baz 2}}}]
(update-in m [:foo :deep] clojure.set/rename-keys {:baz :periwinkle}))
{:foo {:deep {:periwinkle 2, :bar 1}}}
Same as Brian Carper's solution, except the walk namespace already has a specific function for this purpose. All keys at all levels are changed, be they nested inside any sort of collection or seq.
(:use 'clojure.walk)
(def x
{:data1
{:categories
[{:desc "whatever", :name "abc", :id 234}
{:desc "nothing", :name "def", :id 456}]},
:data2
{:categories
[{:desc "whatever", :name "abc", :id 234}
{:desc "nothing", :name "def", :id 456}]}})
(postwalk-replace {:desc :something} x)
{:data1
{:categories
[{:something "whatever", :name "abc", :id 234}
{:something "nothing", :name "def", :id 456}]},
:data2
{:categories
[{:something "whatever", :name "abc", :id 234}
{:something "nothing", :name "def", :id 456}]}}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With