I have a hash-map. I want to iterate over the values and replace each of them depending on the value's type. If the value is an integer, replace it with true
, and if not, replace it with false
. I want this to return a new hash-map with every value updated to either true or false.
(defn my-function [hash-map]
(loop [hash-map hash-map]
(for [value (vals hash-map)]
(if (= Integer (type value))
(recur (assoc hash-map key true))
(recur (assoc hash-map key false))))))
That won't work because Clojure Can only recur from tail position
, but that's the general idea of what I want to do. Any ideas of an effective way to do this? if-let
and update-in
seemed like potential solutions, but I can't quite grasp them.
(reduce-kv (fn [m k v] (assoc m k (= Integer (type v)))) {} m)
Or even shorter if you prefer:
(reduce-kv #(assoc %1 %2 (= Integer (type %3))) {} m)
And to keep the type of map (hash vs. sorted):
(reduce-kv #(assoc %1 %2 (= Integer (type %3))) (empty m) m)
Caveat: the last one doesn't work with records.
The operation you've outlined -- transforming each value in a map, independently -- is actually already implemented in the Functor module.
What you need to do to use it is implement your function that transforms a single value, then fmap
it over your map:
(fmap your-function your-map)
(Don't be misled by the name fmap -- this operation is not specific to maps. Since it's a generic function, it works on anything that has a Functor instance, which also includes lists, sets, and vectors). This is a structure-preserving operation: none of the keys will be changed, no new ones will be added, none will be removed.
If you'd prefer to avoid using a generic function, just check out the implementation:
(defmethod fmap clojure.lang.IPersistentMap
[f m]
(into (empty m) (for [[k v] m] [k (f v)]))) ;;; <== the important part!!
where f = your-function
and m = your-map
.
This library has been moved (is moving? will be moved?) to clojure.algo.generic.functor
. See this for more information, and this for the source.
(letfn [(map-vals [m f]
(into {} (for [[k v] m]
[k (f v)])))]
(map-vals m #(= Integer (type %))))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With