Swift 使用 reduce 和计算增量平均值

标签 swift average

建议是逐步计算平均值 下面的代码是我发现计算增量平均值的最佳方法,以便将其用于大数字和/或大数组

下面是给这个数组加倍的例子

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/

相关文章:

ios - 歧义使用 'subscript' - NSMutableDictionary

ios - 仅用一个旋转轴将 SCNNode 定位在相机前面

dictionary - 如何从 Swift 中的字典中获取键的值?

mysql - 使用左联接查询中的AVG帮助

php - (MYSQL)从具有某些资格的学生列表中计算平均值

ios - 我只想添加 2 个字典的值

swift - 使用 segue 的 datePicker 日期

php - 求关联数组中相同键值的平均值

python - 平均 numpy 数组但保持形状

python - 根据旧字典创建一本新字典,按十年对关键年份进行分组并找出范围的平均值