reactivex重复跳过之间

时间:2017-05-28 17:38:52

标签: reactive-programming reactivex

假设我有以下数据流:

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执行此操作?

2 个答案:

答案 0 :(得分:2)

使用初始值为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');

答案 1 :(得分:0)

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

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

它比我想要的更复杂,但它有效。

编辑6/3/17:

我实际上为我的案子找到了一个更清洁的解决方案。

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));

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

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