2

Is there a way to use Aggregate function (Max, Count, ....) with Buffer before a sequence is completed. When Completed this will produce results, but with continues stream it does not give any results?

I was expecting there is some way to make this work with buffer?

IObservable<long> source;
IObservable<IGroupedObservable<long, long>> group  = source
        .Buffer(TimeSpan.FromSeconds(5))
        .GroupBy(i => i % 3);

IObservable<long> sub = group.SelectMany(grp => grp.Max());

sub.Subscribe(l =>
{
    Console.WriteLine("working");
});
DLeh
  • 23,806
  • 16
  • 84
  • 128
user007
  • 1,122
  • 1
  • 10
  • 30
  • What kind of result would you expect from Count until the actual input is completed? – Lasse V. Karlsen Jan 09 '15 at 15:08
  • How many elements was per buffer batch, or what was max element per group for current batch. What I want to achieve is after grouping get element with max Time per group .SelectMany(g => g.Aggregate((minQuote, fxQuote) => minQuote.Time < fxQuote.Time ? fxQuote : minQuote).Select(quote => quote)); – user007 Jan 09 '15 at 15:09
  • You need to write your own GroupBy for that as GroupBy has no way of knowing when a particular group is finished. – Lasse V. Karlsen Jan 09 '15 at 15:10
  • GroupBy works fine, SelectMany works fine as long as I don't use aggregate function (Max) inside. This is working group.SelectMany(grp => grp.Select(g => new { newProp = g})); – user007 Jan 09 '15 at 15:14
  • GroupBy returns an observable for each group that doesn't know the contents of each group until the entire input sequence has been consumed. As such, GroupBy doesn't work fine as how the groups work is integral to how GroupBy was implemented. If you know that once you've gotten items that belong in a different group, the previous group is completed, you can build a GroupBy that uses that knowledge to complete each group. – Lasse V. Karlsen Jan 09 '15 at 15:16
  • Sorry, my mistake, I do get back IGroupedObservable when subscribe and I do need to wait until Source is completed to get results back. – user007 Jan 09 '15 at 15:23

2 Answers2

5

Use Scan instead of Aggregate. Scan works just like Aggregate except that it sends out intermediate values as the stream advances. It is good for "running totals", which appears to be what you are asking for.

Brandon
  • 38,310
  • 8
  • 82
  • 87
4

All the "statistical" operators in Rx (Min/Max/Sum/Count/Average) are using a mechanism that propagate the calculate value just when the subscription is completed, and that is the big difference between Scan and Aggregate, basically if you want to be notified when a new value is pushed in your subscription it is necessary to use Scan.

In your case if you want to keep the same logic, you should combine with GroupByUntil or Window operators, the conditions to use both can create and complete the group subscription regularly, and that will be used to push the next value.

You can get more info here: http://www.introtorx.com/content/v1.0.10621.0/07_Aggregation.html#BuildYourOwn

By the way I wrote a text related to what you want. Check in: http://www.codeproject.com/Tips/853256/Real-time-statistics-with-Rx-Statistical-Demo-App

J. Lennon
  • 3,311
  • 4
  • 33
  • 64