Phil Gref
Phil Gref

Reputation: 987

Determine and operate on the latest updated sequence in a CombineLatest

I am wondering if there was an existing operator or a certain logic that would allow me to reproduce the behavior of a CombineLatest with 2 source sequences, but with the added ability to determine which of the 2 sequences was modified last. I want to, in turn, use this distinction to change the way I operate when combining the latest result of both sequences.

I think that a good way to express what I want is by giving an example of a method signature that would implement the logic I am talking of.

public static IObservable<TResult> MyOperator<TInLeft, TInRight, TResult>(
    this IObservable<TInLeft> left, 
    this IObservable<TInRight> right, 
    Func<TInLeft, TInRight, bool, TResult> selector)
{
    // ...magic 
} 

In this case, left and right would be the entry sequences and the selector func passed to the method would have its boolean parameter value set to true to indicate that it is the left sequence that was the source of the most recent change and false if it was the right sequence that changed last.

Of course, for the sake of clarity, the method could also be reformulated in the following way

public IObservable<TResult> MyOperator<TInLeft, TInRight, TResult>(
    this IObservable<TInLeft> left, 
    this IObservable<TInRight> right, 
    Func<TInLeft, TInRight, TResult> whenLeft,
    Func<TInLeft, TInRight, TResult> whenRight)
{
    // ... more magic
} 

Where, instead of using a boolean to distinguish the most recently updated sequence, each sequence would have its own contained behavior in the form of a func.

A use case for such an operator would be that I want to have a shared result that depends on some combination of the left and right sequence (just like CombineLatest), but that priority is given to whichever has the newest information. I hope that my intent is clear enough to understand.

Is there an existing operator that has a similar underlying logic or that could be adapted to serve this purpose ? How could I accomplish such a behavior otherwise ? I have a vague idea of some operators that could be of use, but It seems like there could be a lot of different ways and I am just not sure of the best approach to take to achieve what I want.

Upvotes: 2

Views: 230

Answers (2)

NeddySpaghetti
NeddySpaghetti

Reputation: 13495

You can try and use the Timestamp operator in conjunction with CombineLatest. Something like this:

    var obs1 = Observable.Interval(TimeSpan.FromSeconds(1)).Timestamp();
    var obs2 = Observable.Interval(TimeSpan.FromSeconds(2)).Timestamp();

    var result = Observable.CombineLatest(obs1, obs2, (v1, v2) =>
    {
        if(v1.Timestamp < v2.Timestamp)
        {
            Console.WriteLine("v1 " + v1.Timestamp);
            return v1;
        }
        else
        {
            Console.WriteLine("v2 " + v1.Timestamp);
            return v2;
        }       
    });

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

Upvotes: 2

Enigmativity
Enigmativity

Reputation: 117175

Here's what I would do:

var combined =
    source1.Timestamp()
        .CombineLatest(source2.Timestamp(), (ts1, ts2) => new { ts1, ts2 });

combined.Select(x =>
    x.ts1.Timestamp < x.ts2.Timestamp
        ? "source1 first"
        : "source2 first");

Upvotes: 3

Related Questions