N.Singh
N.Singh

Reputation: 53

how to update only a few keys in a map in clojure?

I have a map in which i want to update the values(which are strings) but i want to update only a few keys not all the keys.

I am new and have no idea how to do it.

Is it possible to update only a few keys in a Clojure map keeping the rest same?

Upvotes: 1

Views: 685

Answers (3)

Stefan Kamphausen
Stefan Kamphausen

Reputation: 1665

Trying to summarize comments and answers so far...

There are several ways to update only some of the keys in your map. Which one is the best depends on

  • Is your data structure nested?
    • If nested, use assoc-in instead of assoc or update-in instead of update.
  • Do you compute the new values based on the old one?
    • If you need the old values use update and update-in over assoc and assoc-in.
  • How many keys do you have and how do you have them?
    • The functions assoc, assoc-in, update, and update-in all use recursion under the hood for more than one key. With many keys you may run into stack overflow exceptions. The same is true for the notation using -> which rewrites your code into nested calls.
    • In such cases, use into or merge if you'd use assoc otherwise.
    • Using into or merge would also be easier if you don't have a fixed set of keys to update but something which is computed at run-time.
    • Note that into may be faster than merge as it uses a polymorphic reduce under the hood.
    • If you're computing new values based on the old ones, i.e. would use update otherwise, consider iterating over your map using reduce once and collect the new values. This is more low-level but may avoid iterating twice depending on your scenario.

Examples

Please see (and upvote :-) other responses for examples with assoc, assoc-in, update, and update-in.

(def sample-map {:a 1 :b 2 :c 3})
(def new-values {:b 22 :c 33})
(into sample-map new-values)
(merge sample-map new-values)

Upvotes: 1

fl00r
fl00r

Reputation: 83680

update is a valid way to do it if you want to apply a function to your values. otherwise, you could just assoc new values to the map

(def example {:a "a" :b "b" :c "c"})
(assoc example
       :a "foo"
       :c "bar")
#=> {:a "foo" :b "b" :c "bar")

or update-in for nested data

(def example {:data {:a "a" :b "b" :c "c"}})
(update-in example [:data] assoc 
           :a "foo" 
           :c "bar")
#=> {:data {:a "foo" :b "b" :c "bar"}}

Upvotes: 3

Michiel Borkent
Michiel Borkent

Reputation: 34800

The following will update only keys :a and :b:

(def example {:a 1 :b 2 :c 3})
(-> example
    (update :a inc)
    (update :b inc))
;; {:a 2, :b 3, :c 3}

Upvotes: 2

Related Questions