【问题标题】:applying function in a map to each value in a map based on its key根据其键将映射中的函数应用于映射中的每个值
【发布时间】:2014-04-17 02:04:40
【问题描述】:

假设我有一张地图:

{:name "foo"
 :age "bar"}

还有一个

{:name (fn [val] (println val))
 :age (fn [val] (= val "bar"))}

我想将第二个映射上由:name 键入的函数应用于第一个映射,该映射也由:name 键入,并将:age 键入的函数应用于由:age 键入的第一个映射。如何以clojure方式做到这一点?

【问题讨论】:

    标签: clojure


    【解决方案1】:

    我喜欢这个,如果你需要更多的弹性:

    (defn fmm [m fm]
      (let [f (fn [k] ((get fm k identity) (k m)))
            ks (keys m)]
        (zipmap ks (map f ks))))
    

    【讨论】:

    【解决方案2】:
    (def data { :name "don knotts" 
            :dob "1/1/1940" 
            :cob "Valdosta"  })
    
    (def fxns {:name identity :dob identity :cob clojure.string/reverse})
    
    (defn bmap [data fxn]
      (apply merge (for [[k1 d] data [k2 f] fxn  :when (= k1 k2)]
         {k1 (f d)})))
    
    ;=user>{:cob "atsodlaV", :dob "1/1/1940", :name "don knotts"}
    

    【讨论】:

      【解决方案3】:

      你可以使用合并

      (def m1 {:name "foo"
               :age "bar"})
      
      (def m2 {:name (fn [val] (println val))
               :age (fn [val] (= val "bar"))})
      
      user=> (merge-with #(%1 %2) m2 m1)
      foo
      {:name nil, :age true}
      

      【讨论】:

      • 这很简洁,但仅在两个地图具有完全相同的键时才有效,从问题中并不清楚。
      • @amalloy 感谢您的澄清,我发现这是一个稀有使用功能的很好的使用示例。
      【解决方案4】:

      map 在一张地图上,从另一张地图上得到对应的功能。

      (def m1 {:name "foo"
               :age "bar"})
      
      (def m2 {:name (fn [val] (println val))
               :age (fn [val] (= val "bar"))})
      
      (map (fn [[k v]]
             ((get m2 k) v)) 
           m1)
      

      在您的示例中,地图上的每次迭代都会将一个向量传递给函数:

      [:name "foo"]
      [:age "bar"]
      

      因此将函数参数解构为[[k v]] 会分别为您提供每个键/值。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-05-13
        • 1970-01-01
        • 2020-03-22
        • 2020-08-23
        • 1970-01-01
        • 2018-12-21
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多