简体   繁体   中英

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?

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"}}

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}

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, ie 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)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM