0

入力ストリームをデバウンスする必要があります。

状態 1 の最初の発生時に、5 秒間待機し、最後の状態も 1 であったかどうかを確認する必要があります。信号が安定している場合のみです。

(time)  0-1-2-3-4-5-6-7-8-9
(state) 0-0-0-0-0-1-0-1-0-1
(result)                   -> 1

以下は、不安定な信号の例です。

(time)  0-1-2-3-4-5-6-7-8-9
(state) 0-0-0-0-0-1-0-1-0-0
(result)                   -> 0

バッファを使用してみましたが、バッファには開始点が固定されており、最初のイベントから 5 秒間待機する必要があります。

4

2 に答える 2

4

要件を文字どおりに解釈する

状態 1 の最初の発生時に、5 秒間待機し、最後の状態も 1 であったかどうかを確認する必要があります。信号が安定している場合のみです。

この問題を解決するいくつかの方法を思いつくことができます。私の仮定を明確にするために、最初に 1 が発生してから 5 秒後に生成された最後の値をプッシュしたいだけです。ソース シーケンスから数秒)

ここで、ジガリー ポケリーを使ってシーケンスを再現します。

var source = Observable.Timer(TimeSpan.Zero,TimeSpan.FromSeconds(1))
    .Take(10)
    .Select(i=>{if(i==5 || i==7 || i==9){return 1;}else{return 0;}}); //Should produce 1;
    //.Select(i=>{if(i==5 || i==7 ){return 1;}else{return 0;}});    //Should produce 0;

以下のすべてのオプションは、シーケンスを共有するように見えます。Rx でシーケンスを安全に共有するには、Publish() して接続します。RefCount() 演算子による自動接続を使用します。

var sharedSource = source.Publish().RefCount();

1) このソリューションでは、最初の値 1 を取得し、シーケンスの選択された値を 5 秒のバッファー サイズにバッファーします。これらのバッファの最初のものだけを取ります。このバッファを取得したら、最後の値を取得してプッシュします。バッファーが空の場合、最後の値がバッファーの実行を開始した '1' であるため、1 をプッシュすると仮定します。

sharedSource.Where(state=>state==1)
            .Take(1)
            .SelectMany(_=>sharedSource.Buffer(TimeSpan.FromSeconds(5)).Take(1))
            .Select(buffer=>
            {   
                if(buffer.Any())
                {
                    return buffer.Last();
                }
                else{
                    return 1;
                }
            })
            .Dump();

2) このソリューションでは、有効な値 (1) を取得してからリッスンを開始し、タイマーが終了をトリガーするまですべての値を取得するというアプローチを採用しています。ここから、最後に生成された値を取得します。

var fromFirstValid = sharedSource.SkipWhile(state=>state==0);
fromFirstValid 
    .TakeUntil(
        fromFirstValid.Take(1)
                    .SelectMany(_=>Observable.Timer(TimeSpan.FromSeconds(5))))
    .TakeLast(1)
    .Dump();

3) このソリューションでは、window 演算子を使用して、「1」の最初の値が発生したときに開き、5 秒が経過すると閉じる単一のウィンドウを作成します。繰り返しますが、最後の値を取ります

sharedSource.Window(
                sharedSource.Where(state=>state==1),
                _=>Observable.Timer(TimeSpan.FromSeconds(5)))
            .SelectMany(window=>window.TakeLast(1))
            .Take(1)
            .Dump();

猫の皮をむくにはさまざまな方法があります。

于 2013-03-22T17:47:46.797 に答える
1

Throttleではなく、あなたが望むように(一目で)聞こえBufferますが、ユースケースに関するいくつかの詳細情報がそれを特定するのに役立ちます-とにかくThrottle、ストリームする方法は次のとおりです。

void Main()
{
    var subject = new Subject<int>();
    var source = subject.Publish().RefCount();

    var query = source
        // Start counting on a 1, wait 5 seconds, and take the last value
        .Throttle(x => Observable.Timer(TimeSpan.FromSeconds(5)));

    using(query.Subscribe(Console.WriteLine))
    {
        // This sequence should produce a one
        subject.OnNext(1);
        subject.OnNext(0);
        subject.OnNext(1);
        subject.OnNext(0);
        subject.OnNext(1);
        subject.OnNext(1);
        Console.ReadLine();
        // This sequence should produce a zero
        subject.OnNext(0);
        subject.OnNext(0);
        subject.OnNext(0);
        subject.OnNext(0);
        subject.OnNext(1);
        subject.OnNext(0);
        Console.ReadLine();
    }
}
于 2013-03-21T00:27:24.003 に答える