我想知道是否有一种廉价(性能方面)的选择,可以从一个索引开始搜索满足某些条件的数组元素的索引?
Array.tryFindIndex方法没有startIndex参数。我可以使用Array.skip(n),然后在那里搜索,但似乎为了搜索而创建一个数组开销太大了。我该怎么办呢?
我查看了List,也没有这个参数。我必须使用while ... do吗?有更好的方法吗?
我想知道是否有一种廉价(性能方面)的选择,可以从一个索引开始搜索满足某些条件的数组元素的索引?
Array.tryFindIndex方法没有startIndex参数。我可以使用Array.skip(n),然后在那里搜索,但似乎为了搜索而创建一个数组开销太大了。我该怎么办呢?
我查看了List,也没有这个参数。我必须使用while ... do吗?有更好的方法吗?
module Array =
let tryFindIndexFrom i p (a : _ []) =
let rec loop k =
if k >= a.Length then None
elif p a.[k] then Some k
else loop (k + 1)
if i < 0 then None else loop i
编辑:p
是用于测试数组元素的谓词。 tryFindIndexFrom
的签名与tryFindIndex
相同,但将起始索引添加为第一个参数。
编辑2:为了防止错误使用,添加了对k < 0
的测试。
编辑3:将对k < 0
的测试移出循环,因为只需要检查一次。以下是使用数组索引的惰性序列实现的方法:
最初的回答
let input = [| 'a' .. 'z' |]
seq { 4 .. input.Length - 1 }
|> Seq.tryFind (fun i -> input |> Array.tryItem i = Some 'x')
seq { input.Length - 1 .. -1 .. 4 }
。跟随你的直觉。虽然考虑使用Array.skip
,但明显会浪费分配第二个数组的资源,因此可以更进一步地将其推广到惰性求值的Seq.skip
,并将其与标准的Seq.tryFindIndex
函数组合,并在适用时添加偏移量。
最初的回答:考虑使用Array.skip
,但可能会浪费资源。建议使用Seq.skip
进行惰性求值,并与Seq.tryFindIndex
函数结合使用,如有必要,请添加偏移量。
let tryFindIndexMin n p =
Seq.skip n
>> Seq.tryFindIndex p
>> Option.map ((+) n)
// val tryFindIndexMin : n:int -> p:('a -> bool) -> (seq<'a> -> int option)
[ for i in 0..3 ->
[|"a"; "b"; "a"; "b"|]
|> tryFindIndexMin i ((=) "a") ]
// val it : int option list = [Some 0; Some 2; Some 2; null]
n
个序列项,这可能是较慢的部分。 - TheQuickBrownFox
let
后面添加inline
,F# 编译器有时可以内联谓词,从而避免虚拟调用。此外,有时使用ValueOption<_>
可以避免 GC 压力。因为 OP 谈到了性能便宜的问题。 - Just another metaprogrammer