Mapping a function on the values of a map in Clojure

前端 未结 11 1386
面向向阳花
面向向阳花 2020-11-29 16:03

I want to transform one map of values to another map with the same keys but with a function applied to the values. I would think there was a function for doing this in the c

相关标签:
11条回答
  • 2020-11-29 16:44

    You can use the clojure.algo.generic.functor/fmap:

    user=> (use '[clojure.algo.generic.functor :only (fmap)])
    nil
    user=> (fmap inc {:a 1 :b 3 :c 5})
    {:a 2, :b 4, :c 6}
    
    0 讨论(0)
  • 2020-11-29 16:44
    (defn map-vals
      "Map f over every value of m.
       Returns a map with the same keys as m, where each of its values is now the result of applying f to them one by one.
       f is a function of one arg, which will be called which each value of m, and should return the new value.
       Faster then map-vals-transient on small maps (8 elements and under)"
      [f m]
      (reduce-kv (fn [m k v]
                   (assoc m k (f v)))
                 {} m))
    
    (defn map-vals-transient
      "Map f over every value of m.
       Returns a map with the same keys as m, where each of its values is now the result of applying f to them one by one.
       f is a function of one arg, which will be called which each value of m, and should return the new value.
       Faster then map-vals on big maps (9 elements or more)"
      [f m]
      (persistent! (reduce-kv (fn [m k v]
                                (assoc! m k (f v)))
                              (transient {}) m)))
    
    0 讨论(0)
  • 2020-11-29 16:45

    Taken from the Clojure Cookbook, there is reduce-kv:

    (defn map-kv [m f]
      (reduce-kv #(assoc %1 %2 (f %3)) {} m))
    
    0 讨论(0)
  • 2020-11-29 16:45

    I'm a Clojure n00b, so there may well be much more elegant solutions. Here's mine:

    (def example {:a 1 :b 2 :c 3 :d 4})
    (def func #(* % %))
    
    (prn example)
    
    (defn remap [m f]
      (apply hash-map (mapcat #(list % (f (% m))) (keys m))))
    
    (prn (remap example func))
    

    The anon func makes a little 2-list from each key and its f'ed value. Mapcat runs this function over the sequence of the map's keys and concatenates the whole works into one big list. "apply hash-map" creates a new map from that sequence. The (% m) may look a little weird, it's idiomatic Clojure for applying a key to a map to look up the associated value.

    Most highly recommended reading: The Clojure Cheat Sheet .

    0 讨论(0)
  • 2020-11-29 16:45

    Clojure 1.7 (released June 30, 2015) provides an elegant solution for this with update:

    (defn map-function-on-map-vals [m f]
        (map #(update % 1 f) m))
    
    (map-function-on-map-vals {:a "test" :b "testing"} #(.toUpperCase %))
    ;; => ([:a "TEST"] [:b "TESTING"])
    
    0 讨论(0)
提交回复
热议问题