echox
echox

Reputation: 9850

Clojure: search/replace values in a dynamic nested map/seq

I have a dynamically created map data structure which will later on be parsed into JSON. Therefore the nesting levels, etc. are unknown and depend on the data.

If a key has multiple values, they are represented as maps inside a sequence.

Here is an example:

{:key "value"
:anotherKey "anotherValue"
:foo "test"
:others [ {:foo "test2"} {:foo "test3"} ]
:deeper {:nesting {:foo "test4"} }
}

I now want to search for the key :foo and append "/bar" to the value.

The result should return the modified map:

{:key "value"
:anotherKey "anotherValue"
:foo "test/bar"
:others [ {:foo "test2/bar"} {:foo "test3/bar"} ]
:deeper {:nesting {:foo "test4/bar"} }
}

What would be a clean and simple way to achieve that?

I tried a recursive approach but beside the memory problem of large data structures I'm struggling with returning my appended values.

Upvotes: 2

Views: 575

Answers (1)

sbensu
sbensu

Reputation: 1521

There might be something simpler than this:

(clojure.walk/prewalk 
  (fn [m] 
    (if (and (map? m) (:foo m)) 
      (update-in m [:foo] #(str % "/bar")) 
      m)) 
  {:key "value"
   :anotherKey "anotherValue"
   :foo "test"
   :others [{:foo "test2"} {:foo "test3"}]
   :deeper {:nesting {:foo "test4"}}})

=>
{:anotherKey "anotherValue", 
 :key "value", 
 :deeper {:nesting {:foo "test4/bar"}}, 
 :foo "test/bar", 
 :others [{:foo "test2/bar"} {:foo "test3/bar"}]}

Upvotes: 11

Related Questions