1

Just looking into the Rx join extension method. I cant quite figure out how I would use this to create a key join (using the relational domain instead of the time domain)?

var right = Observable.Range(4, 20);
var left = Observable.Range(0, 30).Where(n => n%2 == 0);
var e = from n1 in right
        join n2 in left on ? equals ?
        select new {n1, n2};
e.Subscribe(j => Console.WriteLine("  n1: {0}, n2: {1}", j.n1, j.n2));

Desired output:

n1: 4, n2: 4
n2: 6, n2: 6
n3: 8, n2: 8
...

Not sure if Join can be used this way...?

EDIT

This works but is it right way to do this (concurrency, performance)?

var e = from n1 in right
        from n2 in left
        where n1 == n2
        select new { n1, n2 };
lukebuehler
  • 4,061
  • 2
  • 24
  • 28
  • Thank you for your help. I just realized I want to the same thing as in this question: http://stackoverflow.com/questions/4911465/how-to-join-multiple-iobservable-sequences – lukebuehler Jan 16 '12 at 18:52

1 Answers1

3

It is important to keep in mind that observables are collections over time - or another way of putting it they are a series of events. For enumerables can be thought of as collections at a moment in time.

It makes sense to join over enumerables - all of the values are available to you the moment in time that you make the join.

It's different when using Rx - it's almost like you need to do some sort of time travel!

So, whenever you try to do a "join" in the Rx world you are saying something like "for some period of time please remember all of the values on observable A and match them with values that happen on observable B during that period."

The Join operator in Rx is specifically used to define custom periods of time and to observe events that occur within the time periods.

The classic situation is that you have a stream of events for whenever an individual enters or exits a room and you want to know who was in the room when some event (say the light was turned on) occurs.

In some ways your second query, the SelectMany query, is just a join that occurs over the lifetime of the two observables and Rx had to remember all of the values to generate matches. It is effectively a pair of collections being built and performing joins as values are added.

The performance of SelectMany is good as long as the input sequences do not get too large (which still may mean that large, but not too large, is OK) and that they eventually terminate. Using hot observables like event patterns from clicks would be a bad choice to do a SelectMany against.

So, if you have a specific time period to join against - use Join - but if you just want to join every value between two observables use SelectMany.

Enigmativity
  • 113,464
  • 11
  • 89
  • 172
  • Good answer, I now realize that I asked slightly the wrong question. The keys I was thinking about are actually time stamps. I basically want to sync two observables when the time stamps of each match. So basically you could take the Range number as a time stamp. And you're right, I do NOT want to make a select many like that, since there might be a lot of data. – lukebuehler Jan 16 '12 at 16:27
  • PS: I had to thing of this talk when you mentioned the rooms: http://channel9.msdn.com/Shows/Going+Deep/Programming-Streams-of-Coincidence-with-Join-and-GroupJoin-for-Rx – lukebuehler Jan 16 '12 at 16:28