【发布时间】:2010-12-08 17:59:05
【问题描述】:
我正在学习 Clojure,想要一些关于惯用用法的建议。作为一个小型统计数据包的一部分,我有一个函数来计算一组数据的模式。 (背景:众数是一组数据中最常见的值。有近十几种已发表的算法来计算它。这里使用的一个来自 Bernard Rosner 的“Fundamentals of Biostatistics”第 6 版。)
(defn tally-map
" Create a map where the keys are all of the unique elements in the input
sequence and the values represent the number of times those elements
occur. Note that the keys may not be formatted as conventional Clojure
keys, i.e. a colon preceding a symbol."
[aseq]
(apply merge-with + (map (fn [x] {x 1}) aseq)))
(defn mode
" Calculate the mode. Rosner p. 13. The mode is problematic in that it may
not be unique and may not exist at all for a particular group of data.
If there is a single unique mode, it is returned. If there are multiple
modes, they are returned as a list. If there is no mode, that is all
elements are present in equal frequency, nil is returned."
[aseq]
(let [amap (tally-map aseq)
mx (apply max (vals amap))
k (keys amap)
f (fn [x] (not (nil? x)))
modes (filter f (map #(if (= mx (get amap %)) %) k))
]
(cond (= 1 (count modes)) (first modes)
(every? #(= mx %) (vals amap)) nil
:else modes)
)
)
我有几个问题:
- 参数。该函数接受单个序列。接受可变数量的参数(如加法函数)是否更惯用?
- 代码气味。看起来“let”比它应该的要复杂一些——这么多的变量赋值。我是否错过了语言或库的任何明显(或不那么明显)的使用,这些使用可以使这种方法更简洁?
提前感谢您的帮助。
【问题讨论】:
标签: statistics clojure