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 => elems(x))
.Zip(src, (results, x) => results.Concat(Enumerable.Repeat(Observable.Return(x), 1)))
.SelectMany(z => z)
.SelectMany(x => 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<T> MergeWithResultPropagation3<T>(this IObservable<T> values, Func<T, IEnumerable<IObservable<T>>> factory)
{
return
values
.Select(x => factory(x))
.Zip(values, AppendValue())
.SelectMany(z => z)
.SelectMany(x => x);
Func<IEnumerable<IObservable<T>>, T, IEnumerable<IObservable<T>>> AppendValue()
{
return (results, value) => 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<T> MergeWithResultPropagation3<T>(this IObservable<T> values, Func<T, IEnumerable<IObservable<T>>> factory)
{
return
values
.Select(x => factory(x))
.Zip(values, (results, value) => AppendValue(results, value))
.SelectMany(z => z)
.SelectMany(x => x);
IEnumerable<IObservable<T>> AppendValue(IEnumerable<IObservable<T>> results, T value)
{
foreach (var result in results) yield return result;
yield return Observable.Return(value);
}
}
IObservable
your own interface because the original one does not supportIEnumerable
and thus does not have theSelectMany
extension. If so, could you include its definition too? \$\endgroup\$ – t3chb0t Apr 8 '17 at 13:32System.Reactive
package from NuGet and added theSystem.Reactive
namespace in LINQPad but it still does not recognize this interface asIEnumerable
. Could you tell me what else I need to do? \$\endgroup\$ – t3chb0t Apr 8 '17 at 13:38system.reactive.core
,system.reactive.infrastructure
, etc...? \$\endgroup\$ – Bruno Costa Apr 8 '17 at 13:39