识别具有最小和最大持续时间的元素序列
Recognize a sequence of elements with minimum and maximum duration
给定一个 IObservable<bool>
和两个 TimeSpan
阈值,minDuration
和 maxDuration
,我需要转换序列以便:
- 跨越
minDuration
和 maxDuration
之间时间的真值序列转换为 "x"
- 跨越
maxDuration
的真值序列转换为 "y"; "y" 应在自第一个真值发出后 maxDuration
时间后发出
为了让事情更清楚,假设 minDuration = 3
、maxDuration = 6
,并假设物品以每秒一个的速度发射:
fffttffttfftttttttttttffftttffffttttf
------------------y--------x-------x-
我的猜测是我需要实现自定义运算符,但作为 RX 新手我不知道如何实现,而且我很难找到超出使用扩展方法组合现有运算符的示例.
欢迎提供有关实现自定义运算符的教程和示例的链接。
如果我理解正确:
- 当您获得大于
minDuration
但小于 maxDuration
的连续真值时,您想要发出 x
.
- 当您获得超过
maxDuration
的连续真值时,您想要发出 y
.
- 在任何其他情况下,什么都不发射。
如果是这样,您的弹珠图应该看起来更像这样:
fffttffttfftttttttttttffftttffffttttf
1234567 123 1234 (numbers for counting guidance)
-----------------y----------x-------x (mine)
------------------y--------x-------x- (yours)
这个x
就只能假的出来了。你不能在 true 上发出它,因为你不知道未来的价值是多少!没有自定义运算符可以为您解决这个问题。
剩下的可以这样解决:
var values = new List<bool> // matches fffttffttfftttttttttttffftttffffttttf
{
false,
false,
false,
true,
true,
false,
false,
true,
true,
false,
false,
true,
true,
true,
true,
true,
true,
true,
true,
true,
true,
true,
false,
false,
false,
true,
true,
true,
false,
false,
false,
false,
true,
true,
true,
true,
false,
};
var original = Observable.Interval(TimeSpan.FromSeconds(1))
.Where(i => i < values.Count)
.Select(i => values[(int)i]);
TimeSpan minDuration = TimeSpan.FromSeconds(3);
TimeSpan maxDuration = TimeSpan.FromSeconds(6);
var trueWindows = original
.TimeInterval()
.Scan(TimeSpan.Zero, (a, t) => t.Value
? a + t.Interval
: TimeSpan.Zero);
var coupledWindows = trueWindows.Scan(new {Previous = TimeSpan.Zero, Current = TimeSpan.Zero},
(o, t) => new {Previous = o.Current, Current = t})
.Publish()
.RefCount();
var xS = coupledWindows.Where(o => o.Previous < maxDuration && o.Previous >= minDuration && o.Current == TimeSpan.Zero).Select(t => "X");
var yS = coupledWindows.Where(o => o.Current >= maxDuration && o.Previous < maxDuration).Select(t => "Y");
至于教程,最好的资源是 http://introtorx.com/. Another somewhat good one is http://rxmarbles.com,尽管它使用非 .NET 函数名称。
给定一个 IObservable<bool>
和两个 TimeSpan
阈值,minDuration
和 maxDuration
,我需要转换序列以便:
- 跨越
minDuration
和maxDuration
之间时间的真值序列转换为 "x" - 跨越
maxDuration
的真值序列转换为 "y"; "y" 应在自第一个真值发出后maxDuration
时间后发出
为了让事情更清楚,假设 minDuration = 3
、maxDuration = 6
,并假设物品以每秒一个的速度发射:
fffttffttfftttttttttttffftttffffttttf
------------------y--------x-------x-
我的猜测是我需要实现自定义运算符,但作为 RX 新手我不知道如何实现,而且我很难找到超出使用扩展方法组合现有运算符的示例.
欢迎提供有关实现自定义运算符的教程和示例的链接。
如果我理解正确:
- 当您获得大于
minDuration
但小于maxDuration
的连续真值时,您想要发出x
. - 当您获得超过
maxDuration
的连续真值时,您想要发出y
. - 在任何其他情况下,什么都不发射。
如果是这样,您的弹珠图应该看起来更像这样:
fffttffttfftttttttttttffftttffffttttf
1234567 123 1234 (numbers for counting guidance)
-----------------y----------x-------x (mine)
------------------y--------x-------x- (yours)
这个x
就只能假的出来了。你不能在 true 上发出它,因为你不知道未来的价值是多少!没有自定义运算符可以为您解决这个问题。
剩下的可以这样解决:
var values = new List<bool> // matches fffttffttfftttttttttttffftttffffttttf
{
false,
false,
false,
true,
true,
false,
false,
true,
true,
false,
false,
true,
true,
true,
true,
true,
true,
true,
true,
true,
true,
true,
false,
false,
false,
true,
true,
true,
false,
false,
false,
false,
true,
true,
true,
true,
false,
};
var original = Observable.Interval(TimeSpan.FromSeconds(1))
.Where(i => i < values.Count)
.Select(i => values[(int)i]);
TimeSpan minDuration = TimeSpan.FromSeconds(3);
TimeSpan maxDuration = TimeSpan.FromSeconds(6);
var trueWindows = original
.TimeInterval()
.Scan(TimeSpan.Zero, (a, t) => t.Value
? a + t.Interval
: TimeSpan.Zero);
var coupledWindows = trueWindows.Scan(new {Previous = TimeSpan.Zero, Current = TimeSpan.Zero},
(o, t) => new {Previous = o.Current, Current = t})
.Publish()
.RefCount();
var xS = coupledWindows.Where(o => o.Previous < maxDuration && o.Previous >= minDuration && o.Current == TimeSpan.Zero).Select(t => "X");
var yS = coupledWindows.Where(o => o.Current >= maxDuration && o.Previous < maxDuration).Select(t => "Y");
至于教程,最好的资源是 http://introtorx.com/. Another somewhat good one is http://rxmarbles.com,尽管它使用非 .NET 函数名称。