这可能非常简单,但我在Rx的学习曲线底部。我花了几个小时阅读文章,观看视频和编写代码,但我似乎对某些看起来应该非常简单的事情存在心理障碍。
我从串口收集数据。我使用Observable.FromEventPattern
来捕获SerialDataReceived
事件并将其转换为可观察的字符序列。到目前为止一切都很好。
现在,我想根据分隔符来解析该字符序列。没有涉及新行,但每个数据包'数据由前导码和终结符包围,两个都是单个字符。为了论证,我们可以说它们是大括号{
和}
。
所以如果我得到了字符序列
j
u
n
k
{
H
e
l
l
o
关于我的角色序列的}
j
u
n
k
,
然后我想在我的字符串序列上发出Hello
或{Hello}
。
我可能错过了一些简单的东西,但我甚至无法弄清楚如何处理这个问题。有什么建议吗?
答案 0 :(得分:6)
使用Publish
和Buffer
:
var source = "junk{Hello}junk{World}junk".ToObservable();
var messages = source
.Publish(o =>
{
return o.Buffer(
o.Where(c => c == '{'),
_ => o.Where(c => c == '}'));
})
.Select(buffer => new string(buffer.ToArray()));
messages.Subscribe(x => Console.WriteLine(x));
Console.ReadLine();
这个输出是:
{Hello}
{World}
这个想法是你可以在Buffer
的调用中使用以下开始和结束选择器。 Publish
的使用是为了确保所有三个Buffer
,开场选择器和结束选择器共享相同的订阅。
source: junk{Hello}junk{World}junk|
opening: ----{----------{----------|
closing: ------}|
closing: ------}|
答案 1 :(得分:0)
使用Scan将您迄今收到的值汇总到聚合字符串中(TAccumulate
是string
),并在每次您将该字符串重置为""
时得到一个结束支架。 (我将把实现聚合功能的工作留给你)。这将产生像
j
ju
jun
junk
junk{
junk{h
junk{hi
junk{hi}
j
ju
...
然后,您可以使用Where仅发出以}
然后最后使用Select删除junk
。
所以完整,应该是
IObservable<string> packetReceived =
serialPort.CharReceived
.Scan(YourAggregationFunction)
.Where(s => s.EndsWith("}"))
.Select(s => s.EverythingAfter("{"));
(我将[{1}}留给您实施)。
请注意,在您尝试使用聚合函数时,使用EverythingAfter
的{{1}}接口来测试它可能更容易,即
IEnumerable
好的,这是一个完整的工作示例
string