8

ランダムな間隔で値を生成するがあり、IObservableこのシーケンスを抑制したいと考えています。私が発見したことの 1 つは、Throttleオペレーターの「スロットリング」の定義が私のものと同じではないということです。

Throttle指定された間隔が無音で経過した後にのみ値を生成します(最後に表示された値を生成します)。スロットリングとは、指定された間隔で値を生成することを意味すると思いました (もちろん、無音でない限り)。

Observable.Interval(100).Select((_,i) => i).Throttle(200)たとえば、 「半分の速度」に調整しているため、(パフォーマンス/タイミングの問題をモジュロとして)偶数を生成することを期待していました。ただし、長さ 200 の無音期間が存在しないため、このシーケンスにはまったく価値がありません。

それで、私がSample望む「スロットリング」動作を実際に行うことを発見しました。Observable.Interval(100).Select((_,i) => i).Sample(200)偶数のシーケンスを生成します(ここでも、パフォーマンス/タイミングの問題をモジュロします)。

ただし、もう 1 つの問題があります。間隔は、最後に「サンプリングされた」値に応じて異なります。私が欲しいのは、次のような演算子を書くことです:

public static IObservable<T> Sample<T>(this IObservable<T> source, Func<T, TimeSpan> intervalSelector);

パラメータは次のサンプルのintervalSelector間隔を生成し、最初のサンプルは...最初の値で取得されるか、追加のパラメータから取得されますが、気にしません。

これを書いてみましたが、うまく機能しない大規模で複雑な構造になってしまいました。私の質問は、これを既存の演算子を使用して (別名、ワンライナーで) 構築できますか?

4

3 に答える 3

6

何時間も後、少し寝て、私はそれを手に入れました。

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)

于 2010-08-16T23:54:12.807 に答える
0

あなたが探しているのは Observable.BufferWithTime ではありませんか?

于 2010-08-16T05:20:33.447 に答える