建议是逐步计算平均值 下面的代码是我发现计算增量平均值的最佳方法,以便将其用于大数字和/或大数组
下面是给这个数组加倍的例子
let values = [14.0,12.0, 23.4,37.5,11.46]
var index = 1
let avg = values.reduce(0.0) { return $0 + ( $1 - $0 ) / Double(index++) }
平均值将为 19.672。并且有效。
从你的角度来看,它是正确的吗?
有没有办法用类似的东西来完成这个:
let avg = values.averageIncr()
我不喜欢的是我必须使用和索引?
[更新]
更进一步,感谢@Martin R 的贡献
protocol NumericType:Equatable {
func +(lhs: Self, rhs: Self) -> Self
func -(lhs: Self, rhs: Self) -> Self
func /(lhs: Self, rhs: Self) -> Self
init(_ value : Int)
}
extension Double : NumericType { }
extension Array where Element : NumericType {
mutating func avg_inc_adding( element: Element, var startAvg:Element? = Element(0) ) throws -> Element{
if count > 0 && startAvg! == Element(0) {
startAvg = self.avg_inc()
}
append(element)
return startAvg! + (element - startAvg!) / Element(self.count - 1)
}
func avg_inc() -> Element {
return enumerate().reduce(Element(0)) { $0 + ( $1.1 - $0 ) / Element($1.0 + 1) }
}
}
通过这种方式,我可以做类似的事情:
var average:Double = values.avg_inc()
do {
average = try values.avg_inc_adding(34.6,startAvg: z)
}catch {
}
符合我的需求,我希望也适合其他人。
最佳答案
无需“外部变量”即可获得相同的结果 与
let avg = values.enumerate().reduce(0.0) { $0 + ( $1.1 - $0 ) / Double($1.0 + 1) }
因为 enumerate()
返回一个索引/元素对序列。
作为扩展方法实现它有点复杂但是 可能的:
protocol NumericType {
func +(lhs: Self, rhs: Self) -> Self
func -(lhs: Self, rhs: Self) -> Self
func /(lhs: Self, rhs: Self) -> Self
init(_ value : Int)
}
extension Double : NumericType { }
extension Array where Element : NumericType {
func averageIncr() -> Element {
return enumerate().reduce(Element(0)) { $0 + ( $1.1 - $0 ) / Element($1.0 + 1) }
}
}
let avg = values.averageIncr()
Array
扩展中的 Element
类型只能限制为
协议(protocol),而不是类型。与例如类似What protocol should be adopted by a Type for a generic function to take any number type as an argument in Swift?要么
How can we create a generic Array Extension that sums Number types in Swift? ,你必须定义一个
包含计算所需的所有方法的协议(protocol)。
限制 Element: FloatingPointType
是不够的,因为
FloatingPointType
协议(protocol)没有定义任何算术运算(+、-、/)。
Swift 3 更新:从 Swift 3/Xcode 8 开始,浮点
类型符合 FloatPoint
协议(protocol)并且定义了
算术运算(+、-、/)。因此自定义协议(protocol)是
不再需要:
extension Array where Element: FloatingPoint {
func averageIncr() -> Element {
return enumerated().reduce(Element(0)) { $0 + ( $1.1 - $0 ) / Element($1.0 + 1) }
}
}
关于Swift 使用 reduce 和计算增量平均值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33842285/