Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/270.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# RX:序列的状态变换,例如指数移动平均_C#_System.reactive - Fatal编程技术网

C# RX:序列的状态变换,例如指数移动平均

C# RX:序列的状态变换,例如指数移动平均,c#,system.reactive,C#,System.reactive,如何在RX中对序列进行简单、有状态的转换 假设我们要对可观测的噪声序列进行指数移动平均变换 每当NoiseSequence勾选时,emaSequence应勾选并返回值 (以前的EMASequenceValue*(1-lambda)+最近的噪声序列值*lambda) 我想我们用的是主题,但具体怎么用 public static void Main() { var rand = new Random(); IObservable<double

如何在RX中对序列进行简单、有状态的转换

假设我们要对可观测的噪声序列进行指数移动平均变换

每当NoiseSequence勾选时,emaSequence应勾选并返回值 (以前的EMASequenceValue*(1-lambda)+最近的噪声序列值*lambda)

我想我们用的是主题,但具体怎么用

    public static void Main()
    {

        var rand = new Random();

        IObservable<double> sequence  = Observable
            .Interval(TimeSpan.FromMilliseconds(1000))
            .Select(value => value + rand.NextDouble());

        Func<double, double> addNoise = x => x + 10*(rand.NextDouble() - 0.5);

        IObservable<double> noisySequence = sequence.Select(addNoise);

        Subject<double> exponentialMovingAverage = new Subject<double>(); // ??? 


        sequence.Subscribe(value => Console.WriteLine("original sequence "+value));
        noisySequence.Subscribe(value => Console.WriteLine("noisy sequence " + value));
        exponentialMovingAverage.Subscribe(value => Console.WriteLine("ema sequence " + value));

        Console.ReadLine();
    }
publicstaticvoidmain()
{
var rand=new Random();
可观测序列=可观测序列
.间隔(时间跨度从毫秒(1000))
.Select(value=>value+rand.NextDouble());
Func addNoise=x=>x+10*(rand.NextDouble()-0.5);
IObservable noisequence=序列。选择(addNoise);
主题指数移动平均值=新主题()???
sequence.Subscribe(value=>Console.WriteLine(“原始序列”+value));
noiseSequence.Subscribe(值=>Console.WriteLine(“noiseSequence”+value));
Subscribe(value=>Console.WriteLine(“ema序列”+value));
Console.ReadLine();
}

对于许多此类计算,
缓冲区是最简单的方法

var movingAverage = noisySequence.Buffer(/*last*/ 3,
    /*move forward*/ 1 /*at a time*/)
    .Select(x => (x[0] + x[1] + x[2]) / 3.0);
如果需要携带状态,请使用
Scan
操作符,它与
Aggregate
类似,只是每次迭代都会生成值


编辑:固定注释语法这是如何将状态附加到序列的。在这种情况下,它计算最后10个值的平均值

var movingAvg = noisySequence.Scan(new List<double>(),
(buffer, value)=>
{
    buffer.Add(value);
    if(buffer.Count>MaxSize)
    {
        buffer.RemoveAt(0);
    }
    return buffer;
}).Select(buffer=>buffer.Average());

谢谢!下面是一个使用扫描的解决方案

    const double lambda = 0.99;
    IObservable<double> emaSequence = noisySequence.Scan(Double.NaN, (emaValue, value) =>
        {
            if (Double.IsNaN(emaValue))
            {
                emaValue = value;
            }
            else
            {
                emaValue = emaValue*lambda + value*(1-lambda);
            }
            return emaValue;
        }).Select(emaValue => emaValue);
常数双λ=0.99;
IObservable emaSequence=noisequence.Scan(Double.NaN,(emaValue,value)=>
{
if(Double.IsNaN(emaValue))
{
emaValue=价值;
}
其他的
{
emaValue=emaValue*λ+值*(1-λ);
}
返回值;
}).选择(emaValue=>emaValue);

在这个特定的平均值示例中有效。更一般地说,如果我们需要内部状态,如何在RX中最好地实现它?也就是说,没有状态。要实现指数移动平均,您需要知道均线的最后一个值。正如Paul所说,您可以使用扫描,通过从种子“状态”开始,并对每个OnNext在该状态上执行一些操作,动态地进行聚合。然后,您可以从状态中选择要在序列之外发布的值。但是,如果您需要访问的不仅仅是当前聚合和最新值,那么窗口操作符可能会有用。为了澄清,我对一种特定的方法不太感兴趣,这种方法可以进行平均值转换,而是进行有状态转换的一般方法。切题:您关于
Window
Buffer
Join
,的文章,而且
GroupJoin
非常有启发性——事实上,我相信我已经多次“引用”你回答与Rx相关的问题
    const double lambda = 0.99;
    IObservable<double> emaSequence = noisySequence.Scan(Double.NaN, (emaValue, value) =>
        {
            if (Double.IsNaN(emaValue))
            {
                emaValue = value;
            }
            else
            {
                emaValue = emaValue*lambda + value*(1-lambda);
            }
            return emaValue;
        }).Select(emaValue => emaValue);