当函数是黑盒时,仅使用一次迭代来做到这一点的唯一方法是使用Seq.cache
函数(它计算一次序列并将结果存储在内存中)或将序列转换为其他内存表示。
当一个函数seq<T>
作为参数时,你甚至不能保证它只会评估一次——标准偏差的通常实现会首先计算平均值,然后再次遍历序列以计算误差的平方。
我不确定您是否可以仅通过一次就可以计算标准偏差。但是,如果使用 . 表示函数,则可以这样做fold
。例如,使用两次传递计算最大值和平均值如下所示:
let maxv = Seq.fold max Int32.MinValue input
let minv = Seq.fold min Int32.MaxValue input
您可以使用这样的单遍来做到这一点:
Seq.fold (fun (s1, s2) v ->
(max s1 v, min s2 v)) (Int32.MinValue, Int32.MaxValue) input
lambda 函数有点难看,但你可以定义一个组合器来组合两个函数:
let par f g (i, j) v = (f i v, g j v)
Seq.fold (par max min) (Int32.MinValue, Int32.MaxValue) input
这种方法适用于可以使用 定义的函数fold
,这意味着它们包含一些初始值(Int32.MinValue
在第一个示例中),然后是一些用于在获得下一个值时更新初始(前一个)状态的函数(然后可能对结果进行一些后处理)。一般来说,应该可以用这种风格重写单通函数,但我不确定这是否可以用于标准偏差。绝对可以为均值完成:
let (count, sum) = Seq.fold (fun (count, sum) v ->
(count + 1.0, sum + v)) (0.0, 0.0) input
let mean = sum / count