我正在尝试组合两个值,它们的值共享一些密钥。
每当第一个observable产生一个新值时,我想产生一个新值,并结合第二个observable的最新值,该值取决于第一个observable的最新值。
伪代码示例:
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)
有什么建议吗?
显然,这可以通过订阅第二个observable并创建一个具有可由键索引的最新值的字典来实现。但我正在寻找一种不同的方法..
使用场景:从股票报价流计算的一分钟价格条。在这种情况下,关键是自动收报机,字典包含具体代码的最新询价和出价,然后在计算中使用。
(顺便说一下,谢谢戴夫和詹姆斯,这是一次非常富有成效的讨论)
(抱歉格式化,很难在iPad上找到它......)
答案 0 :(得分:2)
...你为什么要寻找不同的方法?听起来你对我来说是对的。这是简短的代码...粗略地说它会是这样的:
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#是一种OO语言,线程安全的可变集合的繁重工作已经完成了。
可能有花哨的Rx方法(感觉可能会涉及到连接)......但它的可维护性如何?它将如何表现?
$ 0.02
答案 1 :(得分:2)
我想知道这样一个查询的目的。你介意稍微描述使用场景吗?
尽管如此,以下查询似乎可以解决您的问题。如果您已经有某种方法来识别每个值的来源,那么初始预测就不是必需的,但为了概括起见,我将它们包括在内,以便与您极其抽象的提问模式保持一致。 ; - )
注意:我假设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)));