Luis López
Luis López

Reputation: 159

clojure/clojurescript change just one key in nested map

I have this map:

{:a {:a {:a 1 :b 2}}}

And I want to turn it into this one:

{:a {:a {:x 1 :b 2}}}

I tried this, but -of course- got all :a replaced:

(clojure.walk/postwalk-replace {:a :c} {:a {:a {:a 1 :b 2}}})

-> {:c {:c {:c 1, :b 2}}}

I tried this, but got a result I can't even interpret:

(update-in {:a {:a {:a 1 :b 2}}} [:a :a] clojure.walk/postwalk-replace {:a :c})

-> {:a {:a {1 :c}}}

What can I do?

Upvotes: 1

Views: 174

Answers (1)

cfrick
cfrick

Reputation: 37033

There is a clojure.set/rename-keys. E.g.

(update-in {:a {:a {:a 1 :b 2}}} [:a :a] clojure.set/rename-keys {:a :c})
; → {:a {:a {:b 2, :c 1}}}

The reason, why your example fails is the argument order. postwalk-replace needs the first argument to be the replacement map and the second argument to what is to be renamed. But update-in always sends the traversed things as first argument into the function. So you need to juggle the arguments around (e.g. via an anon-fn or with partial):

(update-in {:a {:a {:a 1 :b 2}}} [:a :a] (partial clojure.walk/postwalk-replace {:a :c}))
; → {:a {:a {:b 2, :c 1}}}

Upvotes: 2

Related Questions