可观察:ANDing源和完成

时间:2015-12-16 19:53:31

标签: c# .net system.reactive

我有一组IObservable<bool> s - 让他们称呼sources - 如果所有输入都为真,我想要和这些值的AND产生true

sources.CombineLatest().Select(values => values.All(x => x))

但是,如果其中一个来源在false的值完成时完成(这意味着所有来源永远不会再为true),我想发信号false并完成

我该怎么做?

2 个答案:

答案 0 :(得分:4)

这是我对它的看法,没有发布和调度程序的需要:

public static IObservable<bool> Foo(
    this IEnumerable<IObservable<bool>> sources)
{
    var projectedSources = sources.Select(source => source
        .Materialize()
        .Scan(
            new
            {
                Latest = true,
                IsCompleted = false
            },
            (tuple, notification) => new
            {
                Latest = notification.HasValue ? notification.Value : tuple.Latest,
                IsCompleted = tuple.IsCompleted || !notification.HasValue
            }));

    return projectedSources
        .CombineLatest()
        .TakeWhile(list => list.All(x => !x.IsCompleted || x.Latest))
        .Select(list => list.All(x => x.Latest))
        .DistinctUntilChanged();
}

首先,我们实现每个源并扫描它,记录它的最后一个值以及源是否已经完成。然后,我们组合这些来源,只有在所有来源未完成或具有最新值true的情况下才从结果中获取。然后,我们将所有源的值投影到单个输出值。

注意:您可能希望使用值true启动源代码(如上面的解决方案中所述)。试验它。

答案 1 :(得分:2)

我认为这样做:

public static IObservable<bool> Foo(
    this IEnumerable<IObservable<bool>> sources)
{                       
    var sourceArray = sources.Select(s => s.Publish().RefCount()).ToArray();

    var terminator = sourceArray
        .ToObservable(Scheduler.Default)
        .SelectMany(x => x.StartWith(true).LastAsync().Where(y => y == false));

    var result = sourceArray
        .CombineLatest(values => values.All(x => x))
        .DistinctUntilChanged()
        .TakeUntil(terminator);

    return result; 
}  

有一些发布可以防止副作用,但是密钥是terminator,它会监视最后一个值为false的流。