2

I am looking for Observable.Window like operator with opening window selector

As example we can take a sequence of natural numbers. I am wondering how to split this sequence into windows so every new window starts if number is greater than 4 or window size has reached 3

Input sequence is IObservable<int> Output sequence is IObservable<IObservable<int>>

Sequence 1 2 5 3 1 1 2 3 1 5 0 will produce windows 1 2; 5 3 1; 1 2 3; 1; 5 0

bublegumm
  • 315
  • 1
  • 3
  • 10

2 Answers2

3

Using C# this works:

var observable =
    source
        .Concat(Observable.Return(-1))
        .Publish(sp =>
            sp.Zip(sp.Skip(1), (x0, x1) => new { x0, x1 })
                .Publish(zsp =>
                    zsp
                        .Window(zsp.Where(x => x.x1 >= 4))
                        .Select(xs => xs.Select(x => x.x0).Window(3))
                        .Merge()));

I get this result:

result

Enigmativity
  • 113,464
  • 11
  • 89
  • 172
1

As per my comment on the question I am unsure whether the sequence 1, 2, 3, 5 should produce the windows 1 2 3 | 5 or 1 2 3 | | 5 (see the empty window which is what Enigmativity's answer produces). My answer does not produce the empty window:

public static IObservable<IObservable<T>> Window<T>(this IObservable<T> source, Func<T, bool> predicate, int maximumWindowSize)
{
    return Observable.Create<IObservable<T>>(obs =>
    {
        var currentWindow = new Subject<T>();
        obs.OnNext(currentWindow);

        var count = 0;

        return source.Subscribe(x =>
        {
            if (count == maximumWindowSize || predicate(x))
            {
                count = 0;
                currentWindow.OnCompleted();
                currentWindow = new Subject<T>();
                obs.OnNext(currentWindow);
            }
            currentWindow.OnNext(x);
            count++;
        }, obs.OnError, () =>
        {
            obs.OnCompleted();
            currentWindow.OnCompleted();
        });
    });
}

This can be used like so:

var windows = source.Window(x => x > 4, 3);
Lukazoid
  • 19,016
  • 3
  • 62
  • 85