我是一名大学教练,试图让Clojure有点乐趣并同时计算我的成绩。我列出了所有学生的数字及其相应的成绩,如下所示:
(def grades-1 (let [s18129 [100 70 85 71 85]
s18121 [80 75 85 81 85]
r18131 [75 60 80 56 75] ...])
;; r before the number is shorthand for repeater
;; and not important to this question
我希望对这些成绩进行调整,以使这些向量中的第一,第二,第三,第四和第五等级分别加权到10%,20%,15%,25%和30%。为了帮助我完成这项任务,我创建了一个辅助函数:
(defn percentify
"adjust raw score to weighted percentile"
[raw percentile]
(* (/ raw 100) percentile))
我想创建另一个将映射成绩列表的函数,并根据其位置,以矢量中每个元素的特定权重将percentify函数应用于每个学生的成绩。这就是我现在正在使用的东西,但我不能在repl中使它工作。我认为这与我如何构建我的类数据有关,或者,我对使用println感到困惑。
(defn finalize [grades-list]
(let [[[student] [a b c d e]] grades-list]
(println
(percentify a 10.0)
(percentify b 20.0)
(percentify c 15.0)
(percentify d 25.0)
(percentify e 30.0))))
然后我想调用这个函数以可读的形式返回最终成绩和学生数。有人可以帮助我走上正轨吗?
答案 0 :(得分:3)
首先,您似乎将每个学生的成绩向量分配到let
形式的单独本地。要在所有等级向量之间映射函数,您需要首先将它们放在单个数据结构中:
(def grades-1 [[100 70 85 71 85]
[80 75 85 81 85]
[75 60 80 56 75]])
现在,将权重向量应用于等级向量的函数将非常有用(percentify
这是您的原始函数):
;; taking weights first for convenient use with partial
(defn percentify-vector [pvec rvec]
(mapv percentify rvec pvec))
最后,我们可以将以上内容映射到等级向量集合中:
(mapv (partial percentify-vector [10.0 20.0 15.0 25.0 30.0]) grades-1)
答案 1 :(得分:1)
数据自然是从学生编号(字符串)到成绩矢量的地图:
(def grades-1 {"s18129" [100 70 85 71 85]
"s18121" [80 75 85 81 85]
"r18131" [75 60 80 56 75]})
...以及要应用于上述的权重向量:
(def grade-weights [10 20 15 25 30])
...从学生编号到最终成绩的地图。我们怎么能这个因素呢?
根据给定weights
向量计算平均值的函数是
(fn [grades] (/ (reduce + 0.0 (map * weights grades)) (reduce + weights)))
......其中
0.0
的初始值强制使用浮点
算术和以下内容将a-map
的每个值转换为该值的函数f
:
(fn [f a-map] (into {} (map (fn [[k v]] [k (f v)]) a-map)))
因此,从等级向量和加权向量的地图提供最终成绩的地图的功能是......
(defn av-grades [gt weights]
(let [weight-av (fn [grades]
(/ (reduce + 0.0 (map * weights grades)) (reduce + weights)))
convert-map (fn [f a-map]
(into {} (map (fn [[k v]] [k (f v)]) a-map)))]
(convert-map weight-av gt)))
而且,果然,......
=>(av-grades grades-1 grade-weights)
{"r18131" 68.0, "s18121" 81.5, "s18129" 80.0}
答案 2 :(得分:0)
我无法改进MichałMarczyk的答案,但我会建议一个可能的选择。目前对你的需求来说可能有点过分了。你想要做的主要是矩阵乘法:你将矩阵乘以一个向量,以产生一个向量。如果需要,可以使用core.matrix库直接完成。假设各个项目等级用于测验。首先,您需要在加载core.matrix库的情况下运行Clojure,例如使用Leiningen。然后在REPL或文件中,您可以这样做:
(use 'clojure.core.matrix)
;; Define quiz grade matrix: Each row is a student, each column is a quiz.
(def quiz-grades [[100 70 85 71 85]
[ 80 75 85 81 85]
[ 75 60 80 56 75]])
;; Define weights representing contributions of each quiz to the final grade.
(def quiz-weights [0.10 0.20 0.15 0.25 0.30])
在这里,我将测验的权重定义为表示1的分数而不是整数的小数,但是使用map
,mapv
或类似的core.matrix很容易在两个表示之间进行转换功能,emap
。现在你可以得到每个学生的最终成绩:
user=> (mmul quiz-grades quiz-weights)
[80.0 81.5 68.0]
(注意:core.matrix有不同的向量和矩阵的底层实现。在我的例子中,我使用了默认的持久向量实现,其中向量和矩阵等价于常规Clojure向量和向量向量。为了轻松地在不同的实现之间切换,最好将Clojure向量嵌入到函数matrix
的调用中,但这对于持久向量实现来说并不是必需的。)