.net 两种变速源都有一种最迟的

.net 两种变速源都有一种最迟的,.net,system.reactive,reactive-programming,.net,System.reactive,Reactive Programming,我有以下案例和我想要达到的结果: L --1---3---4---5---6---7---8- R ---A--------B--CDE-FG--H---I O ---A--------B--C--E---G---H- ---1--------4--5--6---7---H- 所以基本上我有两个相对速度随时间变化的源。结果有时应忽略L元素,有时应忽略R元素。如何构建这种RX 我尝试使用连接、示例、WithLatestFrom、Distincts等,但我总是可以忽略L源中的一些元素,但不能

我有以下案例和我想要达到的结果:

L --1---3---4---5---6---7---8-
R ---A--------B--CDE-FG--H---I

O ---A--------B--C--E---G---H-
  ---1--------4--5--6---7---H-
所以基本上我有两个相对速度随时间变化的源。结果有时应忽略L元素,有时应忽略R元素。如何构建这种RX

我尝试使用连接、示例、WithLatestFrom、Distincts等,但我总是可以忽略L源中的一些元素,但不能忽略R。
我正试图用C语言实现它,但任何语言的答案都会有帮助。

在你的要求中似乎没有规则。您需要能够始终如一地描述L和R中的值会发生什么

这是我能得到的最接近的结果:

var L = new Subject<int>();
var R = new Subject<char>();

var O = L.Select(l => R.Select(r => new { r, l })).Switch();

O.Subscribe(o => Console.WriteLine($"{o.l}{o.r}"));

L.OnNext(1);
R.OnNext('A');
L.OnNext(3);
L.OnNext(4);
R.OnNext('B');
L.OnNext(5);
R.OnNext('C');
R.OnNext('D');
R.OnNext('E');
L.OnNext(6);
R.OnNext('F');
R.OnNext('G');
L.OnNext(7);
R.OnNext('H');
L.OnNext(8);
R.OnNext('I');
这给了我:

1A 4B 5C 5D 5E 6F 6G 7H 8I
另外,从你的大理石图上看,不清楚是F还是6排在第一位。您需要澄清价值顺序和规则,以组合流。

您所要求的似乎没有规则。您需要能够始终如一地描述L和R中的值会发生什么

这是我能得到的最接近的结果:

var L = new Subject<int>();
var R = new Subject<char>();

var O = L.Select(l => R.Select(r => new { r, l })).Switch();

O.Subscribe(o => Console.WriteLine($"{o.l}{o.r}"));

L.OnNext(1);
R.OnNext('A');
L.OnNext(3);
L.OnNext(4);
R.OnNext('B');
L.OnNext(5);
R.OnNext('C');
R.OnNext('D');
R.OnNext('E');
L.OnNext(6);
R.OnNext('F');
R.OnNext('G');
L.OnNext(7);
R.OnNext('H');
L.OnNext(8);
R.OnNext('I');
这给了我:

1A 4B 5C 5D 5E 6F 6G 7H 8I
另外,从你的大理石图上看,不清楚是F还是6排在第一位。您需要澄清组合流的值顺序和规则。

看起来您正在寻找ZipLatest实现。看

编辑:

如果您想要一个实现,而不需要下载库,我认为这将是可行的:

public static IObservable<Tuple<T1, T2>> ZipLatest<T1, T2>(this IObservable<T1> left, IObservable<T2> right)
{
    return Observable.Defer(() =>
    {
        var leftSubject = new BehaviorSubject<bool>(false);
        var rightSubject = new BehaviorSubject<bool>(false);

        return left.Publish(_left =>
            right.Publish(_right =>
            {
                return Observable.CombineLatest(
                    _left,
                    _right,
                    _left.Select(_ => true).Merge(leftSubject),
                    _right.Select(_ => true).Merge(rightSubject), 
                    (l, r, l_bool, r_bool) => Tuple.Create(l_bool, r_bool, l, r)
                )
                    .Where(t => t.Item1 && t.Item2)
                    .Select(t => Tuple.Create(t.Item3, t.Item4))
                    .Do(_ =>
                    {
                        leftSubject.OnNext(false);
                        rightSubject.OnNext(false);
                    });
            })
        );
    });

看起来您正在寻找ZipLatest实现。看

编辑:

如果您想要一个实现,而不需要下载库,我认为这将是可行的:

public static IObservable<Tuple<T1, T2>> ZipLatest<T1, T2>(this IObservable<T1> left, IObservable<T2> right)
{
    return Observable.Defer(() =>
    {
        var leftSubject = new BehaviorSubject<bool>(false);
        var rightSubject = new BehaviorSubject<bool>(false);

        return left.Publish(_left =>
            right.Publish(_right =>
            {
                return Observable.CombineLatest(
                    _left,
                    _right,
                    _left.Select(_ => true).Merge(leftSubject),
                    _right.Select(_ => true).Merge(rightSubject), 
                    (l, r, l_bool, r_bool) => Tuple.Create(l_bool, r_bool, l, r)
                )
                    .Where(t => t.Item1 && t.Item2)
                    .Select(t => Tuple.Create(t.Item3, t.Item4))
                    .Do(_ =>
                    {
                        leftSubject.OnNext(false);
                        rightSubject.OnNext(false);
                    });
            })
        );
    });

这是我目前的尝试;我以后会在编译器中尝试

跟踪最近通过联合收割机发送的最后一个值,并确保在应用操作之前每个值都是唯一的。将此操作定义为扩展方法

public static IObservable<C> ZipLatest<A, B, C>(
    this IObservable<A> sourceA,
    IObservable<B> sourceB,
    Func<A, B, C> op) 
{
    IObservable<Tuple<A, B>> combined = sourceA.CombineLatest(
            sourceB, (a, b) => Tuple.Create(a, b));
    Tuple<A, B> last = null;
    return combined.Where(curr => 
    {
        if (last == null || (last.Item1 != curr.Item1 && last.Item2 != curr.Item2))
        {
            last = curr;
            return true;
        }
        return false;
    }).Select(curr => op(curr.Item1, curr.Item2));
}

这是我目前的尝试;我以后会在编译器中尝试

跟踪最近通过联合收割机发送的最后一个值,并确保在应用操作之前每个值都是唯一的。将此操作定义为扩展方法

public static IObservable<C> ZipLatest<A, B, C>(
    this IObservable<A> sourceA,
    IObservable<B> sourceB,
    Func<A, B, C> op) 
{
    IObservable<Tuple<A, B>> combined = sourceA.CombineLatest(
            sourceB, (a, b) => Tuple.Create(a, b));
    Tuple<A, B> last = null;
    return combined.Where(curr => 
    {
        if (last == null || (last.Item1 != curr.Item1 && last.Item2 != curr.Item2))
        {
            last = curr;
            return true;
        }
        return false;
    }).Select(curr => op(curr.Item1, curr.Item2));
}

谢谢你的回答,我更正了图表。我使用Join或CombineTest获得了与您类似的结果。这里的关键问题是两个源必须遵循相同的规则:我只能在元素之间每隔一个源间隔通知一次。另外,两个源中的任何元素都不能在结果中出现两次。感谢您的回答,我更正了图表。我使用Join或CombineTest获得了与您类似的结果。这里的关键问题是两个源必须遵循相同的规则:我只能在元素之间每隔一个源间隔通知一次。另外,两个来源的元素都不能在结果中出现两次。为什么H7得到输出而不是G7?是的,错了。谢谢你指出。为什么H7得到输出而不是G7?没错,错了。谢谢你指出这一点。