Merging union Observables I am having a scenario where I need to execute observables that depends on the result of the first one. However I need to keep the result of the first observable. I couldn't find any extension that would help me do this. For instance SelectMany does a projection of the first observable discarding the source results. Therefore I made my own extension:

public static IObservable&lt;T&gt; MergeWithResultPropagation&lt;T&gt;(this IObservable&lt;T&gt; src, Func&lt;T, IEnumerable&lt;IObservable&lt;T&gt;&gt;&gt; elems)
{
    return src.SelectMany(result =&gt; elems(result).Union(new[] { Observable.Return(result) }))
        .SelectMany(r =&gt; r);
}


Here's a dummy example:

Observable.Range(1, 3)
.MergeWithResultPropagation(item =&gt; new[]{
    Observable.Return(item * 2), 
    Observable.Return(item * 3)
}).Dump();


Is this an adequate way to solve the problem? Did I miss an extension method that does this?
Union vs Concat

As you addmited, there is no need to use the Union extension because no two items will ever have the same value. Concat would be more appropriate because it'll better show what is going on.

Difference between the two is that 

[ 1, 2 ].Union([2, 3]) = [1, 2, 3]


whereas the same with Concat would be 

[ 1, 2 ].Concat([2, 3]) = [1, 2, 2, 3] 


because of the not clear intention I had a hard time understanding this short code. The descriptions says something else then the implementation.



Zip

I don't know any extension that could do the same job but I think this one could be expressed cleaner by first producing the results and then zipping each result with the corresponding item that lead to this result using the Zip extension. I also think that it's nicer to use Enumerable.Repeat rather then  new []{}

return 
    src
        .Select(x =&gt; elems(x))
        .Zip(src, (results, x) =&gt; results.Concat(Enumerable.Repeat(Observable.Return(x), 1)))
        .SelectMany(z =&gt; z)
        .SelectMany(x =&gt; x);


Functional

To make it even cleaner I suggest encapsulating the Concat in its own method so the final extension could be:

public static IObservable&lt;T&gt; MergeWithResultPropagation3&lt;T&gt;(this IObservable&lt;T&gt; values, Func&lt;T, IEnumerable&lt;IObservable&lt;T&gt;&gt;&gt; factory)
{
    return
        values
            .Select(x =&gt; factory(x))
            .Zip(values, AppendValue())
            .SelectMany(z =&gt; z)
            .SelectMany(x =&gt; x);

    Func&lt;IEnumerable&lt;IObservable&lt;T&gt;&gt;, T, IEnumerable&lt;IObservable&lt;T&gt;&gt;&gt; AppendValue()
    {
        return (results, value) =&gt; results.Concat(Enumerable.Repeat(Observable.Return(value), 1));
    }
}




yield return

Alternatively to new []{} and Concat you could make the helper work with yield return

public static IObservable&lt;T&gt; MergeWithResultPropagation3&lt;T&gt;(this IObservable&lt;T&gt; values, Func&lt;T, IEnumerable&lt;IObservable&lt;T&gt;&gt;&gt; factory)
{
    return
        values
            .Select(x =&gt; factory(x))
            .Zip(values, (results, value) =&gt; AppendValue(results, value))
            .SelectMany(z =&gt; z)
            .SelectMany(x =&gt; x);

    IEnumerable&lt;IObservable&lt;T&gt;&gt; AppendValue(IEnumerable&lt;IObservable&lt;T&gt;&gt; results, T value)
    {
        foreach (var result in results) yield return result;
        yield return Observable.Return(value);
    }
}