要件を文字どおりに解釈する
状態 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();
猫の皮をむくにはさまざまな方法があります。