我从最简单的问题开始我的问题部分是否有可用的Rx Intersect运算符的实现?
基本上我有两个会产生价值的流。 假设流1产生:A,B,C,D,E,F,G 并且流2产生:B,D,F
两个流都将完成且不是无限的(对于后台:它们由我们同时查询的两个不同数据源提供。)
有没有人对如何在Rx世界中实现异步交叉运算符有任何建议?
答案 0 :(得分:4)
这是一个适用于热观察的不同实现,它为你提供了一个集交集,所以如果'c'
在两个流中出现三次,它只会在交叉流中出现一次。
IObservable<char> stream1;
IObservable<char> stream2;
var intersect = Observable
.Merge(stream1.Distinct(), stream2.Distinct())
.GroupBy(c=>c)
.SelectMany(g=>g.Skip(1).Take(1));
示例:
stream1 ---a---b--c--d--e--a-b-c
stream2 -b---a---e---------a-b-c
intersect -----a-b--------e------c
答案 1 :(得分:3)
据我所知,没有“正式”实施。大多数情况下,您需要从两个来源收集值来存储和检查相反来源中的匹配项。这样的事情应该让你开始:
<Extension()>
Public Function Intersect(Of T)(first As IObservable(Of T),
second As IObservable(Of T),
comparer As IEqualityComparer(Of T)
) As IObservable(Of T)
If first Is Nothing Then Throw New ArgumentNullException("first")
If second Is Nothing Then Throw New ArgumentNullException("second")
If comparer Is Nothing Then Throw New ArgumentException("comparer")
Return Observable.Create(Of T)(
Function(obs)
Dim gate As New Object()
Dim firstItems As New HashSet(Of T)(comparer)
Dim secondItems As New HashSet(Of T)(comparer)
Dim firstCompleted, secondCompleted As Boolean
Dim disp As New CompositeDisposable(2)
disp.Add(first.Subscribe(Sub(v)
SyncLock gate
firstItems.Add(v)
If secondItems.Contains(v) Then obs.OnNext(v)
End SyncLock
End Sub,
AddressOf obs.OnError,
Sub()
SyncLock gate
firstCompleted = True
If secondCompleted Then obs.OnCompleted()
End SyncLock
End Sub))
disp.Add(second.Subscribe(Sub(v)
SyncLock gate
secondItems.Add(v)
If firstItems.Contains(v) Then obs.OnNext(v)
End SyncLock
End Sub,
AddressOf obs.OnError,
Sub()
SyncLock gate
secondCompleted = True
If firstCompleted Then obs.OnCompleted()
End SyncLock
End Sub))
Return disp
End Function)
End Function
如果输入包含多个出现次数,则此实现将重复匹配,但仅在两个源中找到它之后才重复匹配。例如
first ----1---2---1----2---1---1----|
second ----------2----1-----------|
out ----------2----1-2---1---1----|
如果不希望重复,您可以检查它是否在相应的源集合中。首先订阅将更改为:
first.Subscribe(Sub(v)
SyncLock gate
'check that the first doesn't already contain this value
If firstItems.Add(v) AndAlso
secondItems.Contains(v) Then obs.OnNext(v)
End SyncLock
End Sub,
AddressOf obs.OnError,
Sub()
SyncLock gate
firstCompleted = True
If secondCompleted Then obs.OnCompleted()
End SyncLock
End Sub)
第二个订阅的变化相似。
答案 2 :(得分:1)
你不能这样做:
var intersect = from x in stream1
from y in stream2
where x == y
select x;