如何使用 "mean" 作为传感器中的最终归约函数?
How do I use "mean" as the final reducing function in a transducer?
我正在尝试估计单位正方形中所有点对的平均距离。
该传感器 returns 随机选择的 x 对点的距离矢量,但最后一步是取该矢量中所有值的平均值。有没有办法使用 mean
作为最终的归约函数(或将其包含在合成中)?
(defn square [x] (* x x))
(defn mean [x] (/ (reduce + x) (count x)))
(defn xform [iterations]
(comp
(partition-all 4)
(map #(Math/sqrt (+ (square (- (first %) (nth % 1)))
(square (- (nth % 2) (nth % 3))))))
(take iterations)))
(transduce (xform 5) conj (repeatedly #(rand)))
[0.5544757422041136
0.4170515673848907
0.7457675423415904
0.5560901974277822
0.6053573945754688]
(transduce (xform 5) mean (repeatedly #(rand)))
Execution error (ArityException) at test.core/eval19667 (form-init9118116578029918666.clj:562).
Wrong number of args (0) passed to: test.core/mean
来自 transduce
的文档:
If init is not supplied, (f) will be called to produce it. f should be
a reducing step function that accepts both 1 and 2 arguments, if it
accepts only 2 you can add the arity-1 with 'completing'.
剖析这个:
- 你的函数需要 0-arity 来产生一个初始值——所以
conj
很好(它产生一个空向量)。
- 您需要提供一个 2 元函数来进行实际的归约
-- 同样
conj
在这里没问题
- 您需要提供 1-arity 函数来完成 - 这里是您想要的
你的
mean
.
因此,正如文档所建议的那样,您可以使用 completing
来提供:
(transduce (xform 5) (completing conj mean) (repeatedly #(rand)))
; → 0.4723186070904141
如果您查看 completing
的源代码,您将了解它是如何生成的
所有这些:
(defn completing
"Takes a reducing function f of 2 args and returns a fn suitable for
transduce by adding an arity-1 signature that calls cf (default -
identity) on the result argument."
{:added "1.7"}
([f] (completing f identity))
([f cf]
(fn
([] (f))
([x] (cf x))
([x y] (f x y)))))
如果您以不同方式实现 mean
函数,则无需在计算平均值之前收集所有值。这是基于 this Java code:
的实现方法
(defn mean
([] [0 1]) ;; <-- Construct an empty accumulator
([[mu n]] mu) ;; <-- Get the mean (final step)
([[mu n] x] ;; <-- Accumulate a value to the mean
[(+ mu (/ (- x mu) n)) (inc n)]))
然后你这样使用它:
(transduce identity mean [1 2 3 4])
;; => 5/2
或者像这样:
(transduce (xform 5) mean (repeatedly #(rand)))
;; => 0.582883812837961
我正在尝试估计单位正方形中所有点对的平均距离。
该传感器 returns 随机选择的 x 对点的距离矢量,但最后一步是取该矢量中所有值的平均值。有没有办法使用 mean
作为最终的归约函数(或将其包含在合成中)?
(defn square [x] (* x x))
(defn mean [x] (/ (reduce + x) (count x)))
(defn xform [iterations]
(comp
(partition-all 4)
(map #(Math/sqrt (+ (square (- (first %) (nth % 1)))
(square (- (nth % 2) (nth % 3))))))
(take iterations)))
(transduce (xform 5) conj (repeatedly #(rand)))
[0.5544757422041136
0.4170515673848907
0.7457675423415904
0.5560901974277822
0.6053573945754688]
(transduce (xform 5) mean (repeatedly #(rand)))
Execution error (ArityException) at test.core/eval19667 (form-init9118116578029918666.clj:562).
Wrong number of args (0) passed to: test.core/mean
来自 transduce
的文档:
If init is not supplied, (f) will be called to produce it. f should be a reducing step function that accepts both 1 and 2 arguments, if it accepts only 2 you can add the arity-1 with 'completing'.
剖析这个:
- 你的函数需要 0-arity 来产生一个初始值——所以
conj
很好(它产生一个空向量)。 - 您需要提供一个 2 元函数来进行实际的归约
-- 同样
conj
在这里没问题 - 您需要提供 1-arity 函数来完成 - 这里是您想要的
你的
mean
.
因此,正如文档所建议的那样,您可以使用 completing
来提供:
(transduce (xform 5) (completing conj mean) (repeatedly #(rand)))
; → 0.4723186070904141
如果您查看 completing
的源代码,您将了解它是如何生成的
所有这些:
(defn completing
"Takes a reducing function f of 2 args and returns a fn suitable for
transduce by adding an arity-1 signature that calls cf (default -
identity) on the result argument."
{:added "1.7"}
([f] (completing f identity))
([f cf]
(fn
([] (f))
([x] (cf x))
([x y] (f x y)))))
如果您以不同方式实现 mean
函数,则无需在计算平均值之前收集所有值。这是基于 this Java code:
(defn mean
([] [0 1]) ;; <-- Construct an empty accumulator
([[mu n]] mu) ;; <-- Get the mean (final step)
([[mu n] x] ;; <-- Accumulate a value to the mean
[(+ mu (/ (- x mu) n)) (inc n)]))
然后你这样使用它:
(transduce identity mean [1 2 3 4])
;; => 5/2
或者像这样:
(transduce (xform 5) mean (repeatedly #(rand)))
;; => 0.582883812837961