シーケンスが無限大の場合、通常のを使用できませんSeq.tryFind
。
ただし、シーケンスが順序付けられている場合、シーケンス内の他の要素が自分の条件を満たすことができないことを検出すると、検索がキャンセルされる可能性があります。
そのような検索を表現するためのエレガントな方法はありますか?
標準関数だけを使用したい場合-このようなものが機能します
let evens = Seq.initInfinite ((*)2)
let has v =
Seq.tryPick (fun x ->
if x = v then Some (Some v)
elif x > v then Some None
else None)
>> Option.bind id
has 40 evens // Some 40
has 41 evens // None
ここに別の可能な解決策があります。@desco が投稿したものと非常に似ていますが、代わりにシーケンス式を使用しており、Seq.tryPick
ネストされたオプション タイプも必要ありません。
let has element input =
seq { for v in input do
if v = element then yield Some v
if v > element then yield None }
|> Seq.head
または、組み込み関数を使用した、より優れたシンプルなソリューションです。を使用Seq.takeWhile
して、探している要素より小さいか等しい要素のみを含むシーケンスの先頭を取得し、シーケンスのSeq.tryFind
この部分で使用します。
let has element input =
input |> Seq.takeWhile (fun x -> x <= element)
|> Seq.tryFind (fun x -> x = element)
または、ポイントフリースタイルが好きな場合(IMHOを読むのが難しくなるため、私はそうしません):
let has element = Seq.takeWhile ((>=) element) >> Seq.tryFind ((=) element)