reactx 重复跳过

reactivex repeated skip between

假设我有以下数据流:

1, 2, 3, a, 5, 6, b, 7, 8, a, 10, 11, b, 12, 13, ...

我想过滤掉 'a' 和 'b'(含)之间的所有内容,无论它们出现了多少次。所以上面的结果是:

1, 2, 3, 7, 8, 12, 13, ...

我如何使用 ReactiveX 做到这一点?

好的。我发布这个以防其他人需要答案。与我上面描述的略有不同的设置只是为了让它更容易理解。

List<String> values = new List<string>()
{
    "1", "2", "3",
    "a", "5", "6", "b", 
    "8", "9", "10", "11",
    "a", "13", "14", "b",
    "16", "17", "18", "19",
    "a", "21", "22", "b",
    "24"
};

var aa = 
    // Create an array of CSV strings split on the terminal sigil value
    String.Join(",", values.ToArray())
    .Split(new String[] { "b," }, StringSplitOptions.None)

    // Create the observable from this array of CSV strings
    .ToObservable()

    // Now create an Observable from each element, splitting it up again
    // It is no longer a CSV string but the original elements up to each terminal value
    .Select(s => s.Split(',').ToObservable()
        // From each value in each observable take those elements
        // up to the initial sigil
        .TakeWhile(s1 => !s1.Equals("a")))

    // Concat the output of each individual Observable - in order
    // SelectMany won't work here since it could interleave the
    // output of the different Observables created above.
    .Concat();

aa.Subscribe(s => Console.WriteLine(s));

打印出来:

1
2
3
8
9
10
11
16
17
18
19
24

它比我想要的要复杂一些,但它确实有效。

编辑 2017 年 6 月 3 日:

我实际上为我的案例找到了更简洁的解决方案。

List<String> values = new List<string>()
{
    "1", "2", "3",
    "a", "5", "6", "b", 
    "8", "9", "10", "11",
    "a", "13", "14", "b",
    "16", "17", "18", "19",
    "a", "21", "22", "b",
    "24"
};

string lazyABPattern = @"a.*?b";
Regex abRegex = new Regex(lazyABPattern);

var bb = values.ToObservable()
    .Aggregate((s1, s2) => s1 + "," + s2)
    .Select(s => abRegex.Replace(s, ""))
    .Select(s => s.Split(',').ToObservable())
    .Concat();
bb.Subscribe(s => Console.WriteLine(s));

代码更简单,更容易理解(即使它使用正则表达式)。

这里的问题是,它仍然不是删除数据流的“重复区域”问题的真正通用解决方案。它依赖于将流转换为单个字符串,对字符串进行操作,然后将其转换回其他形式。如果有人对如何以一般方式处理此问题有任何想法,我很乐意听听。

使用初始值扫描b

1, 2, 3, a, 5, 6, b, 7, 8, a, 10, 11, b, 12, 13, ...

进入

b, 1, 2, 3, a, a, a, b, 7, 8, a, a, a, b, 12, 13, ...

然后过滤掉ab得到

1, 2, 3, 7, 8, 12, 13, ...

在伪代码中

values.scan('b', (s, v) -> if (v == 'a' || v == 'b' || s != 'a') v else s). filter(v -> v != 'a' && v != 'b');