我想知道是否有一个便宜的(性能明智的)选项来搜索从索引开始满足特定条件的数组元素的索引?
Array.tryFindIndex方法没有参数startIndex。我可以做Array.skip(n)然后在那里搜索,但是创建一个仅用于搜索的数组似乎很昂贵。我该怎么做?
我看着List也没有那个参数。 我需要在...期间使用吗?有更好的方法吗?
答案 0 :(得分:5)
基础库试图为您提供方便的功能,但是它们可能无法预期所有用例。如果需要的话,写自己的东西没错:
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
的测试仅需要检查一次,因此已从循环中移出。
答案 1 :(得分:2)
这是一种使用数组索引的惰性序列进行操作的方法:
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 }
。
答案 2 :(得分:2)
遵循您的直觉。考虑到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]