需要状态的自包含的Reactive Extensions辅助方法

问题描述

看看https://eprystupa.wordpress.com/2009/12/18/detecting-running-highlow-prices-using-reactive-extensions-for-net/,它有一个有趣的代码块:

var rnd = new Random();
var Feed = Observable.Defer(() =>
    Observable.Return(Math.Round(30.0 + rnd.NextDouble(),2))
    .Delay(TimeSpan.FromSeconds(1 * rnd.NextDouble())))
    .Repeat();

// Daily low price Feed
double min = double.MaxValue;
var FeedLo = Feed
    .Where(p => p < min)
    .Do(p => min = Math.Min(min,p))
    .Select(p => "New LO: " + p);

// Daily high price Feed
double max = double.MinValue;
var FeedHi = Feed
    .Where(p => p > max)
    .Do(p => max = Math.Max(max,p))
    .Select(p => "New HI: " + p);

// Combine hi and lo in one Feed and subscribe to it
FeedLo.Merge(FeedHi).Subscribe(Console.WriteLine);

上面的方法还可以,并且可以完成工作,但是局部变量maxmin意味着代码是非常具体的,而我想附加 NewLowHi 代码/指标到现有的IObservable<double>就像https://github.com/fiatsasia/Financier一样:

public static IObservable<TSource> SimpleMovingAverage<TSource>(this IObservable<TSource> source,int period)
{
    return source.Buffer(period,1).Select(e => e.Average());
}

创建自包含的NewLowHi指标的最佳实践是什么,我可以在不使用(或至少在内部隐藏)局部变量maxmin的情况下进行订阅

解决方法

您在WordPress网站上引用的代码存在一些缺陷。

由于他们创建def Delete(s,t): list_t=list(t) list_s=list(s) while list_t!=list_s: list_t.pop() #list_t.pop() return "".join(list_t) print(Delete("hello","helloworld")) 的方式很受欢迎,因此每个订阅都将收到一组不同的数字。因此,<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet"/> <table class="table table-bordered" style="table-layout: fixed;"> <colgroup> <col span="1" style="width: 20%;"> <col span="1" style="width: 40%;"> <col span="1" style="width: 20%; white-space: normal;"> <col span="1" style="width: 20%;"> <col span="1" style="width: 20%;"> </colgroup> <tr> <th>Year</th> <th>Month</th> <th>Savings</th> <th>Savings for holiday!</th> <th>Random Words</th> </tr> <tr id='haha'> <td rowspan="3">2020</td> <td rowspan="3">January</td> <td rowspan="3">text in here should be long enough to take more than 1 row</td> </tr> <tr> <td>$100</td> <td>Hello</td> </tr> <tr> <td>$200</td> <td>There</td> </tr> </table> </body>feed的可观察变量将在不同的变量集上工作。

但是情况变得更糟。例如,如果对feedLo进行了两次订阅,则将对feedHi进行两次订阅,但是feedLo仅有一个状态变量,这意味着输出的值将是最小值两种订阅的数量,而不是每种订阅的最低数量。

我将展示如何正确执行此操作,但是首先您的问题是关于如何封装状态的。方法如下:

feed

现在,min源将IObservable<T> feed = Observable .Defer(() => { int state = 42; return Observable... // define your observable here. }); 用作其状态。我们可以继续使用上面的模式重写feed

Random

feed / var feed = Observable .Defer(() => { var rnd = new Random(); return Observable .Generate( 0,x => true,x => x,x => Math.Round(30.0 + rnd.NextDouble(),2),x => TimeSpan.FromSeconds(rnd.NextDouble())); }); / Observable.Generate / Defer模式相比,我更喜欢使用Return

现在介绍如何获取最小值和最大值。

我想要一个Delay,该值可以给我一个可订阅源的单一订阅的高值和低值。 Repeat如下所示:

IObservable<(State state,double value)>

这是我可观察的:

State

现在,我可以调用public enum State { High,Low,} 并从源订阅的一次订阅中获得IObservable<(State state,double value)> feedHighLow(IObservable<double> source) => source.Publish(xs => Observable.Merge( xs.Scan(Math.Min).DistinctUntilChanged().Select(x => (state: State.Low,value: x)),xs.Scan(Math.Max).DistinctUntilChanged().Select(x => (state: State.High,value: x)))); / feedHighLow(feed)值的流。 High调用可确保对源的单一订阅,而Low意味着我可以运行两个不同的可观察变量以分别获取最小值和最大值。

我得到这样的结果:

output

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...