【问题标题】:How can I merge observables once an item in the first observable satisfies a predicate?一旦第一个可观察对象中的项目满足谓词,我如何合并可观察对象?
【发布时间】:2017-05-12 15:04:31
【问题描述】:

我想获取两个 observable,并从第一个 observable 发出,直到其中一个满足谓词,然后开始发出从两者合并的事件,如下所示:

letters:     -A----B---C----d---------e-----f------g--
numbers:     ---1-------2----------3-----4-----5------
predicate:   IsLowerCase()
result:      -A----B---C----d12----3--e--4--f--5---g--

如何在 C# 中使用 System.Reactive 做到这一点?

谢谢

【问题讨论】:

    标签: c# system.reactive


    【解决方案1】:

    Switch 几乎总是关键:

    var letters = new Subject<string>();
    var numbers = new Subject<string>();
    var predicate = lettersPublished.Select(s => s.All(c => char.IsLower(c)));
    
    var numbersCached = numbers.Replay().RefCount();
    
    var dummySubscription = numbersCached.Subscribe();
    
    var combined = lettersPublished.Merge(numbersCached);
    
    var switchFlag = predicate.Where(b => b).Take(1);
    
    var result = switchFlag.StartWith(false).Select(b => b ? combined : letters).Switch();
    
    var resultWithDisposal = Observable.Using(() => dummySubscription, _ => result);
    

    构造两个可观察对象,一个在谓词为真之前(在您的情况下为letters),一个在(combined)之后,然后使用可观察对象在它们之间切换(switchflag)。 dummySubscription 是获取 Replay 以缓存后一个订阅之前的所有值所必需的。 Using 用于转储dummySubscription

    您也可以在一个表达式中完成所有操作(给定 lettersnumbers),如下所示:

    var oneLiner = letters.Publish(_letters => numbers.Replay(_numbers =>  
        _letters
            .Select(s => s.All(c => char.IsLower(c)))
            .Where(b => b)
            .Take(1)
            .StartWith(false)
            .Select(b => b ? _letters.Merge(_numbers) : letters)
            .Switch()
    ));
    

    【讨论】:

    • Switch 是我所缺少的。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-09-14
    • 2020-02-11
    • 1970-01-01
    • 2020-01-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多