如何用函数式方法在Clojure中计算每个向量(列)的均值?
计算CSV列均值的Clojure实现方案
嘿,作为Clojure和函数式编程的初学者,能想到用recur来实现递归处理已经很赞啦!我先帮你把没写完的递归版本补全,再给你一个更贴合函数式风格的简洁写法~
补全你的递归版本函数
你的多arity递归思路是对的,我们只需要补充单个列的均值计算逻辑,以及把结果累加进means向量的步骤:
(defn mean "Calculate the mean for each column" ([columns] (mean columns [])) ([columns means] (if (empty? columns) means (let [current-col (first columns) col-sum (apply + current-col) col-count (count current-col) col-mean (/ col-sum (double col-count))] ; 转成double避免整数除法问题 (recur (rest columns) (conj means col-mean))))))
这个函数的逻辑很清晰:
- 初始调用时传入列集合和空向量作为均值结果的累加器
- 每次递归取出第一个列,计算它的总和与元素个数,再求出均值(用
double转换是为了避免Clojure中整数除法只取整的问题) - 把当前列的均值加入累加器,再递归处理剩下的列
- 当所有列处理完,返回累加的均值向量
更简洁的函数式写法
其实在Clojure中,处理集合的每个元素并返回新集合,用高阶函数map会更符合函数式编程的思想,不需要手动管理递归状态:
(defn column-means [columns] (map #(/ (apply + %) (double (count %))) columns))
如果需要处理空列的边界情况(避免除以0报错),可以加上判断:
(defn column-means [columns] (map (fn [col] (if (empty? col) nil ; 这里可以换成你需要的默认值,比如0 (/ (apply + col) (double (count col))))) columns))
这个版本直接用map遍历每一列,对每个列执行均值计算,代码更简洁易读,也充分利用了Clojure的高阶函数特性。
内容的提问来源于stack exchange,提问作者Vasco Ferreira
相关产品推荐
相关产品推荐

