建议逐步计算平均值 下面的代码是我发现计算增量平均值的最佳方法,以便将它用于大数字和/或大数组
以下是给这个数组加倍的例子
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 {
}
符合我的需要,我希望与其他人合作。
答案 0 :(得分:3)
您可以获得相同的结果,而无需使用"外部变量" 与
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()
Element
扩展程序中的Array
类型只能限制为
协议,而不是类型。与例如类似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?,你必须定义一个
协议,其中包含计算中所需的所有方法。
限制Element: FloatingPointType
是不够的,因为
FloatingPointType
协议没有定义任何算术运算(+, - ,/)。
Swift 3的更新:从Swift 3 / Xcode 8开始,浮点数
类型符合FloatPoint
协议并定义
算术运算(+, - ,/)。因此,自定义协议是
不再需要:
extension Array where Element: FloatingPoint {
func averageIncr() -> Element {
return enumerated().reduce(Element(0)) { $0 + ( $1.1 - $0 ) / Element($1.0 + 1) }
}
}