处理在Clojure的地图传染媒介

Ada*_*dam 17 clojure

我没有找到很多关于对地图矢量进行操作的文档或编码示例.例如,如果我有

(def student-grades 
 [{:name "Billy" :test1 74 :test2 93 :test3 89} 
  {:name "Miguel" :test1 57 :test2 79 :test3 85}
  {:name "Sandy" :test1 86 :test2 97 :test3 99}
  {:name "Dhruv" :test1 84 :test2 89 :test3 94}])
Run Code Online (Sandbox Code Playgroud)

我想为测试平均值添加或关联一个新的键值对,我应该阅读哪些函数?如果有人知道Clojure中地图矢量的任何参考/资源,请分享!非常感谢!

mic*_*slm 11

在这种情况下,您希望在集合上映射一个函数(恰好是一个向量); 对于集合中的每个元素(恰好是一个地图 - 不幸的命名碰撞),你想要生成一个新地图,它包含旧地图的所有键值对,加上一个新键,比方说:avg.

例如

(into [] ; optional -- places the answer into another vector
  (map   ; apply the given function to every element in the collection
    (fn [sg] ; the function takes a student-grade
      (assoc sg ; and with this student-grade, creates a new mapping
        :avg    ; with an added key called :avg
        (/ (+ (:test1 sg) (:test2 sg) (:test3 sg)) 3.0)))
    student-grades  ; and the function is applied to your student-grades vector
))
Run Code Online (Sandbox Code Playgroud)

ps你可以使用(doc fn-name)获取文档; 如果你是Clojure的新手,我建议和irc.freenode.net #clojure上的友好朋友一起出去读一本书 - 我最喜欢的是编程Clojure,但是我正在等待O'Reilly即将推出的Clojure书.屏息以待.

  • 您也可以使用`(mapv ...)`来方便`(into [](map ...))`. (2认同)

mik*_*era 5

Hircus已经提供了一个很好的答案,但这是另一个用于比较的实现:

(defn average [nums]
  (double (/ (apply + nums) (count nums))))

(map 
  #(assoc % :avg (average ((juxt :test1 :test2 :test3) %)))
  student-grades)

=> ({:avg 85.33333333333333, :name "Billy", :test1 74, :test2 93, :test3 89} etc....)
Run Code Online (Sandbox Code Playgroud)

评论意见:

  • 通常有必要将诸如"平均"之类的通用功能分离为一个单独的,命名良好的功能
  • 通常,juxt是一个非常有用的函数,用于从地图中提取特定的组件值列表