首页 > 解决方案 > 对 observable 中第一个元素的特殊处理

问题描述

这似乎应该是微不足道的,但我已经浪费了几个小时。我有一个可观察的字符串:

S:  ---a------b----------c------->

我想以某种方式将其转换为逗号分隔的字符串:

L:  ---a------,b---------,c------>

注意第一项之前没有逗号;这很关键。然后我可以订阅这个序列来输出一个逗号分隔的列表:

L.Subscribe(Console.Write); // "a,b,c,..."

(顺便说一句:S 很慢)。

一个明显的解决方案涉及创建一系列分隔符:

C:  -- --,--,--,--,--,--,--,--,-->

然后我们只是压缩它们:

L = S.Zip(C, (s,c)=>c+s)

创建 C 语言很容易,对吧? C = Observable.Return("").Concat(Observable.Repeat(",")).

但是我看到了无限序列解决方案的两个问题,例如重复:

  1. 对 L.Subscribe()的调用。我真的不想让它阻塞。
  2. 感觉真的很没效率。当我们在等待 S 时,C 正在疯狂地输出值——我们扔掉了 99% 的值。我尝试用 Interval(TimeSpan.Zero) 替换重复并获得 100% 的 CPU!

解决这些无限序列问题会很棒,但我想找到一种通用方法来对第一个元素进行特殊处理也是可以的。无论采用何种解决方案,都不能触及 S 的当前实现。

标签: c#observablereactive

解决方案


您可以通过使用暴露当前元素索引的重载来跳过应用,到第一个元素。.Select()

就像是:

using System;
using System.Reactive.Linq;

namespace RxTest
{
    class Program
    {
        static void Main(string[] args)
        {
            var observable = "abcd".ToObservable()
                .Select((c, i) => i == 0 ? c.ToString() : $",{c}");

            observable.Subscribe(Console.Write); 
        }
    }
}

印刷:

a,b,c,d

希望有帮助。


推荐阅读