我有IObservable
以随机间隔生成值,我想要限制这个序列。我发现的一件事是Throttle
运算符对“限制”的定义与我的定义不同。
Throttle
仅在指定的时间间隔过去静音后生成值(它会产生最后看到的值)。我认为节流意味着在指定的时间间隔产生价值(当然,除非有沉默)。
说,我期望Observable.Interval(100).Select((_,i) => i).Throttle(200)
产生(模数任何性能/时间问题)偶数,因为我把它限制为“半速”。然而,这个序列根本没有产生任何价值,因为从来没有一段长度为200的沉默。
所以,我发现Sample
实际上做了我想要的“限制”行为。 Observable.Interval(100).Select((_,i) => i).Sample(200)
产生(再次,模数任何性能/时间问题)偶数序列。
但是,我还有另一个问题:间隔会有所不同,具体取决于最后的“采样”值。我想要的是编写一个如下所示的运算符:
public static IObservable<T> Sample<T>(this IObservable<T> source, Func<T, TimeSpan> intervalSelector);
intervalSelector
参数生成下一个样本的间隔,第一个样本...取自第一个值或来自其他参数,我不在乎。
我试着写这篇文章,但我最终得到了一个不太合理的大型复杂结构。我的问题是,我可以使用现有的运算符(也就是单行代码)构建它吗?
答案 0 :(得分:5)
很多个小时之后,有一些睡眠,我明白了。
public static IObservable<T> Sample<T>(this IObservable<T> source, Func<T, TimeSpan> intervalSelector)
{
return source.TimeInterval()
.Scan(Tuple.Create(TimeSpan.Zero, false, default(T)), (acc, v) =>
{
if(v.Interval >= acc.Item1)
{
return Tuple.Create(intervalSelector(v.Value), true, v.Value);
}
return Tuple.Create(acc.Item1 - v.Interval, false, v.Value);
})
.Where(t => t.Item2)
.Select(x => x.Item3);
}
这可以按我的方式工作:每次产生一个值x
时,它会停止生成值,直到intervalSelector(x)
时间过去。
答案 1 :(得分:0)
不是你在看什么for Observable.BufferWithTime?
答案 2 :(得分:0)
我以另一种方式做到了,我想与任何有用的人分享。
var random = new Random();
Observable.Return(Unit.Default)
.SelectMany(_ => Observable.Timer(TimeSpan.FromSeconds(random.Next(1, 6))))
.TimeInterval()
.Do(value => Console.WriteLine(value))
.Repeat()
.Subscribe();