I have tried to make a SerialGroupBy operator for Rx.Net. The point of the operator is to work like GroupBy, but each time a new group is created the former is completed. So there’s never more than one group open at a time.
My current "best" implementation is something like this:
public static IObservable<IGroupedObservable<TKey, TElement>> SerialGroupBy<TKey, TSource, TElement>(
this IObservable<TSource> stream, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector) =>
stream.Publish(shared =>
shared.GroupByUntil(keySelector, elementSelector, group =>
shared.DistinctUntilChanged(keySelector)));
And I hoped to get the group closing before the next group starts like tested here:
[Fact]
public void SerialGroupBy()
{
var scheduler = new TestScheduler();
var stream = scheduler.CreateHotObservable(
OnNext(201, "First group"),
OnNext(202, "Second group"),
OnNext(203, "Second group"));
var observer = scheduler.CreateObserver<string>();
stream.SerialGroupBy(x => x.Length, x => x)
.Select(x => x.Subscribe(observer))
.Subscribe();
scheduler.Start();
observer.Messages.ShouldBeLike(
OnNext(201, "First group"),
OnCompleted<string>(202),
OnNext(202, "Second group"),
OnNext(203, "Second group"));
}
But the completion of the first groups comes too late, like:
OnNext(201, "First group"),
OnNext(202, "Second group"),
OnCompleted<string>(202),
OnNext(203, "Second group"));
I can understand why (the opening-observer is notified before the closing-observer as per the implementation of GroupByUntil), but how can I implement it so the groups are non-overlapping?
I have tried several different ways, but it always ends up with a variant of the same problem.