将一个可观察量与另一个可观察量的最新值相结合

本文关键字:观察 另一个 最新 相结合 一个 | 更新日期: 2023-09-27 18:34:25

我正在尝试组合两个值共享某个键的可观察量。

每当第一个可观察量产生新值时,我想生成一个新值,并结合第二个可观察量的最新值,

该选择取决于第一个可观察量的最新值。

伪代码示例:

var obs1 = Observable.Interval(TimeSpan.FromSeconds(1)).Select(x => Tuple.create(SomeKeyThatVaries, x)
var obs2 = Observable.Interval(TimeSpan.FromMilliSeconds(1)).Select(x => Tuple.create(SomeKeyThatVaries, x)
from x in obs1
  let latestFromObs2WhereKeyMatches = …
  select Tuple.create(x, latestFromObs2WhereKeyMatches)

有什么建议吗?

显然,这可以通过订阅第二个可观察量并创建一个字典来实现,该字典具有可由键索引的最新值。但我正在寻找一种不同的方法..

使用场景:根据股票报价流计算的一分钟价格柱线。在这种情况下,键是股票代码,字典包含混凝土股票代码的最新要价和买入价,然后在计算中使用。

(顺便说一下,谢谢戴夫和詹姆斯,这是一次非常富有成效的讨论)

(对格式感到抱歉,很难在iPad上正确获得。

将一个可观察量与另一个可观察量的最新值相结合

...您为什么要寻找不同的方法?听起来你对我来说是正确的。这是简短,简单的代码...粗略地说,它将是这样的:

var cache = new ConcurrentDictionary<long, long>();    
obs2.Subscribe(x => cache[x.Item1] = x.Item2);    
var results = obs1.Select(x => new {
    obs1 = x.Item2,
    cache.ContainsKey(x.Item1) ? cache[x.Item1] : 0
});

根结底,C# 是一种面向对象的语言,线程安全可变集合的繁重工作已经为您完成。

可能有花哨的 Rx 方法(感觉可能涉及连接)......但它的可维护性如何?它将如何表现?

$0.02

我想知道这种查询的目的。您介意描述一下使用场景吗?

不过,似乎以下查询可能会解决您的问题。如果你已经有某种方法来识别每个值的起源,那么最初的预测就没有必要了,但为了概括起见,我把它们包括在内,以与你极其抽象的提问模式保持一致。;-)

注意:我假设someKeyThatVaries不是您显示的共享数据,这就是为什么我还包含术语anotherKeyThatVaries;否则,整个查询对我来说真的没有意义。

var obs1 = Observable.Interval(TimeSpan.FromSeconds(1))
                     .Select(x => Tuple.Create(someKeyThatVaries, x));
var obs2 = Observable.Interval(TimeSpan.FromSeconds(.25))
                     .Select(x => Tuple.Create(anotherKeyThatVaries, x));
var results = obs1.Select(t => new { Key = t.Item1, Value = t.Item2, Kind = 1 })
                  .Merge(
              obs2.Select(t => new { Key = t.Item1, Value = t.Item2, Kind = 2 }))
                  .GroupBy(t => t.Key, t => new { t.Value, t.Kind })
                  .SelectMany(g =>
                    g.Scan(
                      new { X = -1L, Y = -1L, Yield = false },
                      (acc, cur) => cur.Kind == 1
                                  ? new { X = cur.Value, Y = acc.Y, Yield = true }
                                  : new { X = acc.X, Y = cur.Value, Yield = false })
                      .Where(s => s.Yield)
                      .Select(s => Tuple.Create(s.X, s.Y)));