C# 反应性试验,以观察不同和重复的值

C# 反应性试验,以观察不同和重复的值,c#,system.reactive,rx.net,C#,System.reactive,Rx.net,我编写测试是为了观察Distinc操作 public class Test: ReactiveTest { [Fact] public void Observe_distint_nonDistinc() { var scheduler = new TestScheduler(); var source = scheduler.CreateHotObservable( OnNext(100, "a"),

我编写测试是为了观察
Distinc
操作

public class Test: ReactiveTest {
    [Fact]
    public void Observe_distint_nonDistinc() {
        var scheduler = new TestScheduler();
        var source = scheduler.CreateHotObservable(
            OnNext(100, "a"),
            OnNext(110, "b"),
            OnNext(200, "a"),
            OnNext(220, "c"),
            OnNext(221, "a")
        );


        var results = scheduler.CreateObserver<string>();
        source.Distinct().Subscribe(results);

        scheduler.AdvanceBy(1000);

        results.Messages.AssertEqual(OnNext(100,"a"),OnNext(110,"b"),OnNext(220,"c"));
    }
}
公共类测试:ReactiveTest{
[事实]
公共无效观察\u区分\u不区分(){
var scheduler=newtestscheduler();
var source=scheduler.CreateHotObservable(
OnNext(100,“a”),
OnNext(110,“b”),
OnNext(200,“a”),
OnNext(220,“c”),
OnNext(221,“a”)
);
var results=scheduler.CreateObserver();
source.Distinct().Subscribe(结果);
调度程序提前(1000);
结果.Messages.AssertEqual(OnNext(100,“a”)、OnNext(110,“b”)、OnNext(220,“c”);
}
}

测试通过了,但是我不确定如何同时观察副本。我尝试了一些与
Publish
combinelateest
的组合,但是我觉得它们不值得一提。我的
replicate
流应该只有两项
OnNext(200,“a”)、OnNext(221,“a”)
以下是一个完整的解决方案:

[Fact]
public void ObserveDistinctNonDistinct()
{
    var scheduler = new TestScheduler();
    var source = scheduler.CreateHotObservable(
        OnNext(100, "a"),
        OnNext(110, "b"),
        OnNext(200, "a"),
        OnNext(220, "c"),
        OnNext(221, "a")
    ).Publish();

    var distinctResults = scheduler.CreateObserver<string>();

    source
        .Distinct()
        .Subscribe(distinctResults);

    var nonDistinctResults = scheduler.CreateObserver<string>();

    (from letter in source
        group letter by letter
        into groupedLetters
        from count in groupedLetters
            .Window(Observable.Never<string>())
            .SelectMany(ol =>
                ol.Scan(0, (c, _) => ++c))
        where count > 1
        select groupedLetters.Key)
    .Distinct()
    .Subscribe(nonDistinctResults);

    source.Connect();

    scheduler.AdvanceBy(1000);

    distinctResults.Messages.AssertEqual(OnNext(100, "a"), OnNext(110, "b"), OnNext(220, "c"));
    nonDistinctResults.Messages.AssertEqual(OnNext(200, "a"));
}
[事实]
public void observeDistinctNondistict()
{
var scheduler=newtestscheduler();
var source=scheduler.CreateHotObservable(
OnNext(100,“a”),
OnNext(110,“b”),
OnNext(200,“a”),
OnNext(220,“c”),
OnNext(221,“a”)
).Publish();
var distinctResults=scheduler.CreateObserver();
来源
.Distinct()
.订阅(distinctResults);
var nonDistinctResults=scheduler.CreateObserver();
(来源于信函)
逐字分组
分组
从分组字母计数
.Window(可观察的.Never())
.SelectMany(ol=>
ol.扫描(0,(c,)=>++c))
其中计数>1
选择groupedLetters.Key)
.Distinct()
.认购(无差别结果);
source.Connect();
调度程序提前(1000);
AssertEqual(OnNext(100,“a”)、OnNext(110,“b”)、OnNext(220,“c”);
无差别结果.消息.资产质量(OnNext(200,“a”);
}
在第二次出现任何重复项时匹配

使用方法语法:

source
    .GroupBy(s => s)
    .SelectMany(g =>
        g.Window(Observable.Never<string>())
            .SelectMany(ol =>
                ol.Scan(0, (c, _) => ++c))
            .Where(l => l > 1)
            .Select(_ => g.Key))
    .Distinct()
    .Subscribe(nonDistinctResults);
源代码
.GroupBy(s=>s)
.SelectMany(g=>
g、 窗口(Observable.Never())
.SelectMany(ol=>
ol.扫描(0,(c,)=>++c))
.其中(l=>l>1)
.选择(=>g.Key))
.Distinct()
.认购(无差别结果);

直到我找到一种更快的实现方法,我想发布我的自定义
CollectDublicates
扩展方法。现在考试如预期的那样通过了

public class Test : ReactiveTest {
    [Fact]
    public void Observe_distint_nonDistinc() {
        var scheduler = new TestScheduler();
        var source = scheduler.CreateHotObservable(
            OnNext(100, "a"),
            OnNext(110, "b"),
            OnNext(200, "a"),
            OnNext(220, "c"),
            OnNext(221, "a")
        ).Publish();


        var distinnctResults = scheduler.CreateObserver<string>();
        source.Distinct().Subscribe(distinnctResults);
        var duplicatesResults = scheduler.CreateObserver<string>();
        source.CollectDuplicates().Subscribe(duplicatesResults);
        source.Connect();
        scheduler.AdvanceBy(1000);

        distinnctResults.Messages.AssertEqual(OnNext(100, "a"), OnNext(110, "b"), OnNext(220, "c"));
        duplicatesResults.Messages.AssertEqual(OnNext(200,"a"),OnNext(221,"a"));
    }
}

public static class RxEx{
    class DubplicateCollector<T> : IEqualityComparer<T> {
        readonly Subject<T> _matches = new Subject<T>();
        public IObservable<T> Matches => _matches;

        public bool Equals(T x, T y) {
            var @equals = x.Equals(y);
            if (equals)
                _matches.OnNext(x);
            return @equals;
        }

        public int GetHashCode(T obj) {
            return obj.GetHashCode();
        }
    }

    public static IObservable<TSource> CollectDuplicates<TSource>(this IObservable<TSource> source) {
        var dubplicateCollector = new DubplicateCollector<TSource>();
        var compositeDisposable = new CompositeDisposable { source.Distinct(dubplicateCollector).Subscribe() };
        return Observable.Create<TSource>(observer => {
            var disposable = dubplicateCollector.Matches.Subscribe(observer.OnNext, observer.OnError, observer.OnCompleted);
            compositeDisposable.Add(disposable);
            return () => compositeDisposable.Dispose();
        });

    }
}  
公共类测试:ReactiveTest{
[事实]
公共无效观察\u区分\u不区分(){
var scheduler=newtestscheduler();
var source=scheduler.CreateHotObservable(
OnNext(100,“a”),
OnNext(110,“b”),
OnNext(200,“a”),
OnNext(220,“c”),
OnNext(221,“a”)
).Publish();
var distinntresults=scheduler.CreateObserver();
source.Distinct().Subscribe(distinntresults);
var duplicatesResults=scheduler.CreateObserver();
source.CollectDuplicates().Subscribe(duplicatesResults);
source.Connect();
调度程序提前(1000);
distinntresults.Messages.AssertEqual(OnNext(100,“a”)、OnNext(110,“b”)、OnNext(220,“c”);
重复结果.Messages.AssertEqual(OnNext(200,“a”)、OnNext(221,“a”);
}
}
公共静态类RxEx{
DubplicateCollector类:IEqualityComparer{
只读主题匹配=新主题();
public IObservable Matches=>\u Matches;
公共布尔等于(TX,TY){
var@equals=x.equals(y);
如果(等于)
_匹配项OnNext(x);
返回@equals;
}
公共int GetHashCode(T obj){
返回obj.GetHashCode();
}
}
公共静态IObservable CollectDuplicates(此IObservable源){
var dubplicateCollector=新的dubplicateCollector();
var compositeDisposable=new compositeDisposable{source.Distinct(dubplicateCollector.Subscribe()};
返回可观察的。创建(观察者=>{
var disposable=dubplicateCollector.Matches.Subscribe(observer.OnNext、observer.OnError、observer.OnCompleted);
可合成。添加(一次性);
return()=>compositeDisposable.Dispose();
});
}
}  

你好,亚伦。你能用lambda表达式而不是查询表达式来写这个吗?我一直在苦苦挣扎:(没关系,我明白了!起初我没有意识到我会使用
Buffer
,但我不是作者:)啊,哈哈!我没有意识到。作者您好:),谢谢您的回答,但是当
a
存在超过2次时,解决方案就不起作用了。你能重构到一个更通用的解决方案吗更新了我的答案。