1

Is there Clojure function that swaps values of two keys in persistent map? I mean something like this:

(defn swap-keys [map k1 k2]
  (let [f (get map k1) s (get map k2)]
    (assoc map k1 s k2 f)))

(swap-keys {:a 1 :b 2 :c 3 :d 4} :a :c)
;; => {:a 3, :b 2, :c 1, :d 4}
foki
  • 8,624
  • 6
  • 33
  • 32
  • Possible duplicate of [What is the idiomatic way to swap two elements in a vector](http://stackoverflow.com/questions/5979538/what-is-the-idiomatic-way-to-swap-two-elements-in-a-vector); there is no difference between a map and a vector in this case. – Sam Estep Mar 23 '16 at 21:55
  • @Elogent I already know how to achieve desired effect, I'm rather searching for a function in Clojure standard library that do this job for me. So, my question is not how to do this but what Clojure function (if there is any) do this job and therefore question you mentioned is different from mine. – foki Mar 23 '16 at 22:08
  • In any case, two distinct questions may admit of the same answer. :) – galdre Mar 23 '16 at 22:12
  • @galdre Of course they can, but this is not that situation. Even responses are distinct. One possible answer to my question is this one beneath - `clojure.set/rename-keys` (a standard Clojure function) while answer to mentioned question is an user defined function. – foki Mar 23 '16 at 22:23

1 Answers1

12

The best I know of is this:

(clojure.set/rename-keys {:a 1 :b 2 :c 3 :d 4}
                         {:a :c, :c :a})
;; {:c 1, :b 2, :a 3, :d 4}

You can use it to do more than just a two-way swap, if you want:

(clojure.set/rename-keys {:a 1 :b 2 :c 3 :d 4}
                         {:a :b,
                          :b :c,
                          :c :d,
                          :d: :a})
;; {:b 1, :c 2, :d 3, :a 4}

Edit: A benefit (probably) to this approach over the "naive" solution is that it performs a check to make sure the necessary keys actually exist:

=> (defn swap [m k1 k2] (assoc m k1 (m k2) k2 (m k1)))
=> (swap {:a 1 :b 2 :c 3} :a :d)
;; {:a nil, :b 2, :c 3, :d 1}

=> (clojure.set/rename-keys {:a 1 :b 2 :c 3} {:a :d, :d :a})
;; {:b 2, :c 3, :d 1}
galdre
  • 2,319
  • 17
  • 31