首页 > 解决方案 > 我可以自动计算 tcl 中某些数据的移动平均值吗?

问题描述

我写了一个程序来计算一些数据的移动平均值。问题是我不能自动化,我的意思是如果我想通过 10 步或更多步骤来完成这个过程,那么用交换条款写 10 行是不明智的。

通过 4 个步骤计算移动平均线的部分是:

     set aux  [lindex $line 4]
     set T [lindex $line 1]
     set aux1 [lrange $valores 1 1]
       set valores [lreplace $valores 0 0 $aux1] 
       
     set aux1 [lrange $valores 2 2]
       set valores [lreplace $valores 1 1 $aux1]
     
     set aux1 [lrange $valores 3 3]
       set valores [lreplace $valores 2 2 $aux1]
       
     set aux1 [lrange $valores 4 4]
       set valores [lreplace $valores 3 3 $aux1]
     
       set valores [lreplace $valores 4 4 $aux]
       set promP [avg $valores]

我知道我必须使用 for 循环,但我所做的尝试没有奏效。

标签: tclmoving-average

解决方案


假设您在数据上保留一个窗口,这并不太难。诀窍是制定一个程序来完成关键工作。

set WINDOW_SIZE 10
set storedData {}

proc updateMovingAverage {value} {
    global storedData WINDOW_SIZE

    set storedData [lreplace [list {*}$storedData $value] 0 end-$WINDOW_SIZE]
    return [expr {[tcl::mathop::+ {*}$storedData] / double([llength $storedData])}]
}

或者你可以创建一个类:

oo::class create MovingAverage {
    variable window size

    constructor {{windowSize 10}} {
        set window {}
        set size $windowSize
    }

    method item {value} {
        set window [lreplace [list {*}$window $value] 0 end-$size]
        return
    }

    method average {} {
        return [expr {[tcl::mathop::+ {*}$window] / double([llength $window])}]
    }
}

该类将添加项目和计算平均值分开。后者现在是 Tcl 中的标准模式。添加项目的技巧是将项目附加到列表中,然后如果列表的前面大于所需的窗口,则将其修剪掉;是list {*}$thing $value追加一个项目,lreplace THING 0 end-$wantedLength是前缀修剪(它用一个空的项目序列替换它们)。


这是一个更有效的版本。

oo::class create MovingAverage {
    variable window size index

    constructor {{windowSize 10}} {
        set window {}
        set size $windowSize
        set index 0
    }

    method item {value} {
        lset window $index $value
        set index [expr {($index + 1) % $size}]
        return
    }

    method average {} {
        return [expr {[tcl::mathop::+ {*}$window] / double([llength $window])}]
    }
}

这使用了这样一个事实,即从 8.6 开始(在集成类时完全巧合),该lset命令可以将项目附加到列表中。


推荐阅读