述語を使用してシーケンスをフィルタリングする関数を作成したいのですが、結果には、述語がfalseを返す最初の項目も含まれるはずです。
F#にbreakキーワードがあった場合、ロジックは次のようになります。
let myFilter predicate s =
seq {
for item in s do
yield item
if predicate item then
break
}
Seq.takeWhileとSeq.skipWhileの組み合わせを試してみました。次のようなものです。
Seq.append
(Seq.takeWhile predicate s)
(Seq.skipWhile predicate s |> Seq.take 1)
...しかし問題は、述語に一致する最初の項目がtakeWhileとskipWhileの間で失われることです。
また、入力シーケンスは怠惰であるため、シーケンスを消費し、後で決定を行うソリューションは実行可能ではないことに注意してください。
何か案は?
ありがとう!
編集:すべての答えをたくさんありがとう!こんなに速く反応することは期待していませんでした。それぞれをすぐに見ていきます。ここで、もう少しコンテキストを示したいと思います。シェルを実装する次のコーディングカタについて考えてみます。
let cmdProcessor state = function
| "q" -> "Good bye!"
| "h" -> "Help content"
| c -> sprintf "Bad command: '%s'" c
let processUntilQuit =
Seq.takeWhile (fun cmd -> cmd <> "q")
let processor =
processUntilQuit
>> Seq.scan cmdProcessor "Welcome!"
module io =
let consoleLines = seq { while true do yield System.Console.ReadLine () }
let display : string seq -> unit = Seq.iter <| printfn "%s"
io.consoleLines |> processor|> io.display
printf "Press any key to continue..."
System.Console.ReadKey ()|> ignore
この実装には、「さようなら」が出力されないという問題があります。コマンドqが入力されたとき。
私がやりたいのは、 「q」を含む「q 」までのすべてのコマンドを処理するように、関数processUntilQuitを実装することです。