代码之家  ›  专栏  ›  技术社区  ›  R. Martinho Fernandes

反应性延长:节流阀/间隔不同的样品

  •  7
  • R. Martinho Fernandes  · 技术社区  · 14 年前

    我有一个 IObservable 它以随机间隔生成值,我想限制这个序列。我发现的一件事是 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 参数生成下一个样本的间隔,第一个样本…不是在第一个值上取的,就是从一个附加参数取的,我不在乎。

    我试着写这篇文章,但最后我得到了一个巨大的复杂的结构,它不能很好地工作。我的问题是,我可以使用现有的操作符(也就是说,使用一行程序)来构建它吗?

    2 回复  |  直到 12 年前
        1
  •  5
  •   Softlion    12 年前

    几个小时后,我睡了一会儿,就明白了。

    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) 时间流逝。

        2
  •  0
  •   Ana Betts    14 年前

    你不是在看什么 for Observable.BufferWithTime ?