How to combine a slow moving observable with the most recent value of a fast moving observable

依然范特西╮ 提交于 2019-12-22 14:55:09

问题


A friend asked me this - I thought it was a good question so I am reposting it and my answer here:

I have these two streams:

var slowSource = Observable.Interval(TimeSpan.FromSeconds(1));
var fastSource = Observable.Interval(TimeSpan.FromMilliseconds(100));

and I’d like to combine them so that I produce output pairs which contain - The next value from slowSource - The most recent value from fastSource

I only want one output pair per value from slowSource. For example, the first three output values might look something like this:

0,8
1,18,
2,28

A join gets me close but I end up with more than one output per slowSource (due to the way that the durations overlap, I guess):

var qry = slowSource.Join(
          right: fastSource,
          leftDurationSelector: i => fastSource,
          rightDurationSelector: j => fastSource,
          resultSelector: (l, r) => {return new {L = l, R = r};})

.Subscribe(Console.WriteLine);

Using a GroupJoin and a Select produces output that looks about right:

var qry2 = slowSource.GroupJoin(
              right: fastSource,
              leftDurationSelector: i => fastSource,
              rightDurationSelector: j => fastSource,
              resultSelector: (l, r) => {return new {L= l, R = r};}
              )
          .Select(async item => {
            return new {L = item.L, R = await item.R.FirstAsync()};})
          .Subscribe(Console.WriteLine);

However, this doesn’t feel like a great approach; there must be a better way that uses the other combinators to do stuff like this in a simpler way. Is there?


回答1:


How about this overload of Zip which combines an IObservable with an IEnumerable. It uses MostRecent() to get a sample of the latest value of a stream as the enumerable.

slowSource.Zip(fastSource.MostRecent(0), (l,r) => new {l,r})



回答2:


Observable.CombineLatest http://msdn.microsoft.com/en-us/library/hh211991(v=vs.103).aspx can help and then you need to resample the fastSource at the rate of the slowSource.

var combinedObservable = slowSource.CombineLatest
    ( fastSource.Sample(slowSource)
    , (s,f)=>new {s,f}
    );


来源:https://stackoverflow.com/questions/20980512/how-to-combine-a-slow-moving-observable-with-the-most-recent-value-of-a-fast-mov

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!