Data structures clojure中向量的分解列表中每个元素的映射
我是一名大学教师,我想找点乐子,同时计算我的成绩。我已将我所有的学生编号及其相应的成绩列成如下所示:Data structures clojure中向量的分解列表中每个元素的映射,data-structures,vector,clojure,mapping,destructuring,Data Structures,Vector,Clojure,Mapping,Destructuring,我是一名大学教师,我想找点乐子,同时计算我的成绩。我已将我所有的学生编号及其相应的成绩列成如下所示: (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
(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
user=> (mmul quiz-grades quiz-weights)
[80.0 81.5 68.0]
我希望对这些年级进行调整,使这些向量中的第一、二、三、四和五年级的权重分别为10%、20%、15%、25%和30%。为了帮助我完成此任务,我创建了一个助手函数:
(defn percentify
"adjust raw score to weighted percentile"
[raw percentile]
(* (/ raw 100) percentile))
;; taking weights first for convenient use with partial
(defn percentify-vector [pvec rvec]
(mapv percentify rvec pvec))
我想创建另一个函数,它将映射到成绩列表,并根据向量中每个元素的位置,以特定权重将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))))
然后我想调用这个函数以可读的形式返回带有学生人数的最终成绩。有人能帮我走上正轨吗 首先,您似乎在以
let
的形式将每个学生的分数向量分配给一个单独的局部变量。要跨所有等级向量映射函数,首先需要将它们放在单个数据结构中:
(def grades-1 [[100 70 85 71 85]
[80 75 85 81 85]
[75 60 80 56 75]])
现在,将权重向量应用于等级向量的函数将非常有用(percentify
这是您的原始函数):
最后,我们可以在坡度向量集合中映射上述内容:
(mapv (partial percentify-vector [10.0 20.0 15.0 25.0 30.0]) grades-1)
首先,您似乎在以
let
的形式将每个学生的分数向量分配给一个单独的局部变量。要跨所有等级向量映射函数,首先需要将它们放在单个数据结构中:
(def grades-1 [[100 70 85 71 85]
[80 75 85 81 85]
[75 60 80 56 75]])
现在,将权重向量应用于等级向量的函数将非常有用(percentify
这是您的原始函数):
最后,我们可以在坡度向量集合中映射上述内容:
(mapv (partial percentify-vector [10.0 20.0 15.0 25.0 30.0]) grades-1)
我无法改进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
,很容易在这两种表示之间进行转换。现在,您可以按如下方式获得每个学生的最终分数:
(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
user=> (mmul quiz-grades quiz-weights)
[80.0 81.5 68.0]
(注意:core.matrix有不同的向量和矩阵的底层实现。在我这里的示例中,我使用了默认的持久向量实现,其中向量和矩阵等效于常规Clojure向量和向量的向量。为了在不同的实现之间轻松切换,最好嵌入在调用函数
matrix
时关闭上述向量,但持久化向量实现不需要这样做。)我无法改进MichałMarczyk的答案,但我会提出一个可能的替代方案。目前,这可能过于满足您的需要。您需要做的基本上是矩阵乘法:将矩阵乘以向量以生成向量。如果需要,可以直接使用core.matrix库。Le假设单项成绩用于测验。首先,您需要在加载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
,可以很容易地在这两种表示之间进行转换。现在,您可以像这样获得每个学生的最终分数:
(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
user=> (mmul quiz-grades quiz-weights)
[80.0 81.5 68.0]
(注意:core.matrix有不同的向量和矩阵的底层实现。在我这里的示例中,我使用了默认的持久向量实现,其中向量和矩阵等效于常规Clojure向量和向量的向量。为了在不同的实现之间轻松切换,最好嵌入Clojure vectors在调用函数
matrix
,但这不是永久性vector实现所必需的。)数据自然是从学生编号(字符串)到成绩向量的映射:
(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])
…绘制一张从学生人数到最终成绩的地图。我们如何考虑这一点
根据给定的权重
向量计算平均值的函数为
(fn [grades] (/ (reduce + 0.0 (map * weights grades)) (reduce + weights)))
…在哪里
的初始值强制使用浮点 算术和0.0
- 权重加起来不需要达到1.0或100,特别是任何数字。 包括缩放
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}
数据自然是从学生编号(字符串)到分数向量的映射:
(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])
…绘制一张从学生人数到最终成绩的地图。我们如何考虑这一点
根据给定的权重
向量计算平均值的函数为
(fn [grades] (/ (reduce + 0.0 (map * weights grades)) (reduce + weights)))
…在哪里
的初始值强制使用float0.0