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, ...
然后过滤掉a
和b
得到
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, 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, ...
然后过滤掉a
和b
得到
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');