如果我有无限序列,我就不能使用普通Seq.tryFind
。
但是,如果序列是有序的,那意味着当我检测到序列中没有其他元素可以满足我的条件时,可以取消搜索。
有没有一种优雅的方式来表达这样的搜索?
答案 0 :(得分:5)
如果你只想使用标准功能 - 这样的话会起作用
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
答案 1 :(得分:3)
这是另一种可能的解决方案。它与@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)
或者如果你喜欢无点的风格(我没有,因为它更难以阅读恕我直言):
let has element = Seq.takeWhile ((>=) element) >> Seq.tryFind ((=) element)