0

Given an IObservable of objects which have an IObservable child property, how do I go about filtering the main observable to only include instances where the child property has at least X number of items.

For example the following test case has an IObservable containing 2 MyClass. The first contains an observable of 5 integers and the second of 2. So my question is how to I filter the IObservable of MyClass to include only instances which contain 4 or more numbers?

[TestClass]
public class TestClass
{
    public class MyClass
    {
        public IObservable<int> Numbers { get; set; }
    }

    [TestMethod]
    public void Test()
    {
        //Arrange       
        var data = new []
        {
            new MyClass()
            {
                Numbers = new Observable.Range(100, 5)
            },
            new MyClass()
            {
                Numbers = new Observable.Range(200, 2)
            }
        };

        var observableData = data.ToObservable();

        //Act
        //TODO: set filtered so that it includes
        // all instances of MyClass which have 4
        // or more items in Numbers
        IObservable<List<MyClass>> filtered = observableData

        //Assert
        IObservable<List<MyClass>> observableResult = 
            filtered.Aggregate(new List<MyClass>(), 
                (l, o) => 
                    { 
                        l.Add(o); 
                            return l; 
                    });

        var result = observableResult.Wait();
        //expected result should include data[0] because
        // is contains 5 numbers but exclude data[1] 
        // because it only contains 2.
        var expected = new List<MyClass>() { data[0] };

        CollectionAssert.AreEquivalent(expected, result);
    }
}

Any help is appreciated.

1adam12
  • 985
  • 5
  • 13

1 Answers1

0

Solution:

IObservable<MyClass> filtered = observableData
    .SelectMany(c => c.Numbers
        .Skip(3)
        .Take(1)
        .Select(_ => c)
    );

In English: For each instance of MyClass, produce an observable that skips the first 3 numbers, then takes one. Map that taken number to the original instance of MyClass. We use SelectMany to flatten the produced observables into one.

Shlomo
  • 14,102
  • 3
  • 28
  • 43