(F#) 查找二维数组中元素的索引

Cod*_*Guy 5 arrays f# multidimensional-array

我目前在查找二维数组中特定元素的索引时遇到一些问题。我知道标准数组可以使用 findIndex ,如下所示。

let wantedElemented = 5
let index = Array.findIndex(fun x -> x = wantedElemented) array
Run Code Online (Sandbox Code Playgroud)

我的问题是,如何将其应用于二维数组(矩形)。有没有比迭代整个数组比较每个元素更有效的方法?

for row in 0 .. max do
        for col in 0 .. max do
            if array.[row,col] = wantedElement then 
            let index = (row,col)
            index
            else (-1,-1)
Run Code Online (Sandbox Code Playgroud)

如果我确实必须迭代整个数组,我将如何在不使用选项类型的情况下处理 else 条件

Fyo*_*kin 5

回应您的评论:是的,数组不能与头尾列表匹配。但他们确实有迹象!:-)

递归函数不必对数据结构进行递归。递归路径可以由不同的东西定义。例如:为什么我们不从零到最大(或返回)递归数组索引?

let find2D needle (arr: int [,]) = 
    let rec go x y =
          if   y >= arr.GetLength 1 then None
          elif x >= arr.GetLength 0 then go 0 (y+1)
          elif arr.[x,y] = needle   then Some (x,y)
          else go (x+1) y
    go 0 0
Run Code Online (Sandbox Code Playgroud)

上面的解决方案将逐行扫描数组,直到找到needle,此时它将立即返回。

或者,您可以自己生成一系列可选索引,然后用于Seq.tryPick选择该序列中不是的第一个元素None

let find2D needle (arr: int [,]) = Seq.tryPick id <| seq {
    for i in 0..(arr.GetLength 0 - 1) do
        for j in 0..(arr.GetLength 1 - 1) do
            if arr.[i,j] = needle 
                then yield Some (i,j) 
                else yield None
}
Run Code Online (Sandbox Code Playgroud)

由于序列的工作方式(它们是惰性的),这只会迭代直到Some找到第一个序列,然后停止。这稍微更简单(就可读性而言),但性能也比上面的普通递归解决方案稍差,因为在这里我们会产生创建和维护序列的开销。