合并最新的,但只推左边
我需要实现一个 CombineLatest
版本(我在这里将其称为 WithLatest
),它为左侧的每个项目和右侧的最新项目调用选择器。它不应该只推动右侧的项目发生变化。
我认为这是构建Observable.Create
还是现有扩展的组合并不是特别重要;无论哪种方式,我都会将其设为“盒装”扩展方法。
示例
var left = new Subject<int>();
var right = new Subject<int>();
left.WithLatest(right, (l,r) => l + " " + r).Dump();
left.OnNext(1); // <1>
left.OnNext(2); // <2>
right.OnNext(1); // <3>
right.OnNext(2); // <4>
left.OnNext(3); // <5>
应该产生
2 1
3 2
编辑:我的示例的逻辑是:
- 左侧填充 1。右侧为空,没有推送任何值。
- Left 更新为 2(它忘记了之前的值)。右侧仍然是空的,因此没有任何内容被推送。
- Right 填充为 1,因此 Left = 2(最新值),Right = 1 被压入。 到目前为止,
WithLatest
和CombineLatest
之间没有任何区别, - 右侧已更新 - 没有推送任何内容。 这就是不同之处
- Left 更新为 3,因此 Left = 3,Right = 2(最新值)被推送。
有人建议我尝试:
var lr = right.ObserveOn(Scheduler.TaskPool).Latest();
left.Select(l => l + " " + lr.First()).Dump();
但这会阻止我的测试的当前线程。
I need to implement a version of CombineLatest
(I'll call it WithLatest
here) that calls the selector for every item on the left and the latest item on the right. It shouldn't push for items on the right changing only.
I think whether this is built Observable.Create
or a combination of existing extensions is not particularly important; I'll be making this a "boxed" extension method either way.
Example
var left = new Subject<int>();
var right = new Subject<int>();
left.WithLatest(right, (l,r) => l + " " + r).Dump();
left.OnNext(1); // <1>
left.OnNext(2); // <2>
right.OnNext(1); // <3>
right.OnNext(2); // <4>
left.OnNext(3); // <5>
should yield
2 1
3 2
Edit: The logic of my example goes:
- Left becomes populated with 1. Right is empty, no values pushed.
- Left becomes updated with 2 (it forgets the previous value). Right is still empty, so nothing is pushed.
- Right becomes populated with 1, so Left = 2 (the latest value), Right = 1 is pushed. Up to this point, there is no difference between
WithLatest
andCombineLatest
- Right is updated -- nothing is pushed. This is what's different
- Left is updated with 3, so Left = 3, Right = 2 (the latest value) is pushed.
It's been suggested that I try:
var lr = right.ObserveOn(Scheduler.TaskPool).Latest();
left.Select(l => l + " " + lr.First()).Dump();
but this blocks on the current thread for my test.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
您可以使用现有的运算符来完成此操作。
Publish
确保我们只订阅right
一次,并在rs
的所有订阅者之间共享订阅。MostRecent
将IObservable
转换为IEnumerable
,它始终从源可观察值生成最近发出的值。IObservable
和IEnumerable
之间的Zip
都会发出一个值。SkipUntil
跳过在right
发出值之前发生的对(l, r)
。You can do this using existing operators.
Publish
ensures we only ever subscribe toright
once and share the subscription among all subscribers tors
.MostRecent
turns anIObservable<T>
into anIEnumerable<T>
that always yields the most recently emitted value from the source observable.Zip
betweenIObservable<T>
andIEnumerable<U>
emits a value each time the observable emits a value.SkipUntil
skips the pairs(l, r)
which occur beforeright
ever emits a value.我也对“仅向左侧推送”的
CombineLatest
有同样的需求。我将该解决方案设为
Observable.Sample
的“重载”,因为这就是该方法的作用:它使用
采样器
(左)对源
(右)进行采样,并具有提供resultSelector
的附加功能(如CombineLatest)。I also had the same need for a
CombineLatest
which "pushes only for the left".I made the solution an "overload" of
Observable.Sample
, because that's what the method does:It samples a
source
(right) with asampler
(left), with the additional capability of providing aresultSelector
(like in CombineLatest).根据帖子作者选择的解决方案,我认为有一个更简单的解决方案,利用 DistinctUntilChanged:
或者即使
您只关心
leftSource
的不同值Based on the solution picked by the post author I think there's an even simpler solution utilizing DistinctUntilChanged:
or even
if you only care about distinct values of
leftSource
我今天为项目制作了一个 RX 运算符来执行此操作。
这是我的解决方案:
I made a RX operator for project today that does this.
Here's my solutions:
在最新的System.Reactive上,我们可以使用
WithLatestFrom
扩展方法。结果将正确如下。
On latest System.Reactive, we can use
WithLatestFrom
extension method.The result would be below correctly.
这是使用 Create 的 hacky 方法 - 并没有真正构建它,如果它实际上不起作用,那就是我的错:)
Here's the hacky way using Create - didn't actually build it, mea culpa if it doesn't actually work :)