2

I am looking to combine the first two sequences as this Marble diagram depicts

CoincidenceWhere

  1. In this example different lottery players pick numbers, and the numbers they pick are indicated by the color of the small dot on the first line.
  2. When winning numbers are decided (line 2)
  3. Lottery winners need to be determined (output on line 3). For lottery winners the small dot represents the player that won.

Desired Outputs

  • So for the red winning numbers, it is not the latest lottery player that won, but it happens to be the third black player
  • For the brown winning numbers it is the first blue player that should be put on the output stream
  • And for the last red winning numbers, it should the last red numbers that won (white player) and not the first red numbers (black player)
  • Note that the output should contain both the player and the numbers (objects), including their associated properties such as player name, and amount of money won associated with the winning numbers etc (this could be achieved by having a selector Func)

Rx Solutions?

  • I tried using .Zip, .When, .CombineLatest, .Buffer, etc, but could not achieve the results desired?
  • Is there anything native in the API that can be used or what kind of custom combination would achieve the desired outputs?
Community
  • 1
  • 1
Cel
  • 6,467
  • 8
  • 75
  • 110

1 Answers1

2

Your choice of colours for the players and colours for the numbers made things a bit confusing.

Nevertheless, this worked for me.

Start with:

var picks = new Subject<KeyValuePair<string, string>>(); // key == number, value = player
var numbers = new Subject<string>();

Then build a sequence of dictionary of picks by number:

var scanned =
    picks
        .Scan(new Dictionary<string, string>(), (d, kvp) =>
        {
            // You need a new dictionary each time
            var d2 = new Dictionary<string, string>(d);
            d2[kvp.Key] = kvp.Value;
            return d2;
        });

Now combine using .Switch():

var query =
    scanned
        .Select(d =>
            numbers.Select(n => new
            {
                player = d[n],
                number = n
            }))
        .Switch();

That's it.

Here's the code that runs it:

query.Subscribe(x => Console.WriteLine(x));

picks.OnNext(new KeyValuePair<string, string>("Brown", "Blue"));
picks.OnNext(new KeyValuePair<string, string>("Grey", "Green"));
picks.OnNext(new KeyValuePair<string, string>("Red", "Black"));
picks.OnNext(new KeyValuePair<string, string>("Grey", "Yellow"));
numbers.OnNext("Red");
numbers.OnNext("Brown");
picks.OnNext(new KeyValuePair<string, string>("Grey", "Black"));
picks.OnNext(new KeyValuePair<string, string>("Red", "White"));
numbers.OnNext("Red");

Here are the results I got:

results

Enigmativity
  • 113,464
  • 11
  • 89
  • 172
  • thanks! how would you keep only the last x players in the dictionary as im expecting loads in the long run and it is known that the old ones can be discarded after some point in time – Cel Jun 12 '15 at 13:18
  • 1
    This would be a place to use `IImmutableDictionary`, since every dictionary that comes out of the scan differs from the previous one by a single addition. Also, in your `query` where you set `player = d[n]`, you might want a check to set `player` to `null` if `d` does not contain `n`. – Timothy Shields Jun 12 '15 at 14:43