用RX压缩重复的流

时间:2018-01-28 02:44:32

标签: c# system.reactive rx.net

我有两个热门观察者,我不想错过任何通知

第一个observable产生数字

  

1-2-3-4

和第二个字符串

  

A-B

我正在寻找一种方法来拉链它们以产生下一个输出

  

a-1b-2a-3b-4a-5

所以我想要的是无限期地重复第二个流,直到第一个流被取消订阅。我尝试了下一个产生所需输出的测试。但是我永远不会Repeat,因为我不知道如何停下来测试结果。此外,我使用了ReplaySubject,我手动完成,这意味着我无法收到任何新通知。

    class MyClass:ReactiveTest{
        [Fact]
        public void MethodName4() {
            var strings = new ReplaySubject<string>();
            var testScheduler = new TestScheduler();
            testScheduler.Schedule("", TimeSpan.FromTicks(10), (scheduler, s) => {
                strings.OnNext("a");
                strings.OnNext("b");
                strings.OnCompleted();
            });

            var numbers = testScheduler.CreateHotObservable(OnNext(100, 1), OnNext(200, 2), OnNext(300, 3), OnNext(400, 4), OnNext(500, 5));
            numbers.Zip(Observable.Defer(() => strings).Repeat(3), (i, s) => (i, s)).Subscribe();
            testScheduler.AdvanceBy(500);
        }

    }

2 个答案:

答案 0 :(得分:1)

我想我找到了一个我将尝试描述的解决方案。

重复热观察是没有意义的,因为它永远不会完成。但是,您可以重复此热门观察窗口。我从@Enigmativity重构了这个answer来重复所有值而不是最后一个值。

    public static IObservable<T> RepeatAllDuringSilence<T>(this IObservable<T> source, TimeSpan maxQuietPeriod,
        IScheduler scheduler=null, IObservable<T> inner=null) {
        if (scheduler==null)
            scheduler=Scheduler.Default;
        if (inner == null)
            inner = source;
        return Observable.Create<T>(observer => {
            var replay = inner.Replay(scheduler);
            var sequence = source.Select(x => Observable.Interval(maxQuietPeriod, scheduler).SelectMany(l => replay).StartWith(x)).Switch();
            return new CompositeDisposable(replay.Connect(), sequence.Subscribe(observer));
        });
    }

然后在我的测试中使用此方法我设法在没有完成ReplaySubject或丢失未来通知的情况下获得预期结果,因为我改变了原始可观察量的温度。

class MyClass : ReactiveTest {
    [Fact]
    public void MethodName4() {
        var strings = new Subject<string>();
        var testScheduler = new TestScheduler();
        testScheduler.Schedule("", TimeSpan.FromTicks(10), (scheduler, s) => {
            strings.OnNext("a");
            strings.OnNext("b");
        });
        testScheduler.Schedule("", TimeSpan.FromTicks(20), (scheduler, s) => {
            strings.OnNext("c");
        });

        var numbers = testScheduler.CreateHotObservable(OnNext(10, 1), OnNext(20, 2), OnNext(30, 3), OnNext(40, 4), OnNext(50, 5));
        numbers.Zip(strings.RepeatAllDuringSilence(TimeSpan.FromTicks(10),testScheduler), (i, s) => (i, s)).Subscribe(tuple => WriteLine(tuple));
        testScheduler.AdvanceBy(50);
    }

}
  

(1,a)
    (2,b)
    (3,c)
    (4,a)
    (5,b)

答案 1 :(得分:0)

这不能解决您的问题吗? :

  void TestMergedPairs()
    {
        var source1 = Observable.Range(1,9999);
        var source2 = Observable.Range(65, 2).Repeat();


        var z = source1.Zip(source2,(x,y)=> { return new { left = x, right = y }; })
             .TakeWhile((v)=>v.left<1000);


        z.Subscribe(x => { Console.WriteLine( x.left +" "+x.right ); });
    }

如果没有,那么不清楚你的问题是什么。如果你希望能够不断重复第二个可观察者的历史内容,那么你的&#34; a&#34;,&#34; b&#34;可能以后会变成&#34; a&#34;,&#34; b&#34;,&#34; c&#34;然后应该迭代这个3个字母的序列,然后你的源可能是聚合历史窗口的.Scan的结果。