递归迭代F#中的数组

时间:2014-08-24 23:11:00

标签: arrays recursion f# iteration

这是一个相当简单的请求,但我在使用F#的语法时遇到了问题。我需要创建一个函数来递归迭代二维数组,每次满足条件时增加一个计数器。在这种情况下,该函数将ID作为参数,然后检查内部数组中ID的存在次数。我在考虑这样的事情:

let runner array count =  
    match count with  
    |0 -> (exit loop)  
    |n -> (perform function)  
        runner array count-1

对于递归迭代函数的一般结构。但是,有几点我不确定。在F#中退出递归循环(即基本情况)的条件是什么?我如何构建它,以便它遍历主数组和子数组以检查ID?假设我不能使用可变函数,那么如何使计数器随着递归循环的每次运行而增加?任何帮助将不胜感激。

3 个答案:

答案 0 :(得分:3)

有一种更通用的方法。你想折叠2d数组。他们没有在Array2D模块中定义折叠,但你可以写一个。

let fold f state (arr: 'a [,]) =
    Seq.cast<'a> arr
    |> Seq.fold f state

我们&#34;作弊&#34;在这里,cast会给我们一个平面的元素序列,然后我们将这些元素传递给一个常规的折叠。所以现在你可以这样做:

 array |> fold (fun counter e -> if cond e then counter+1 else counter) 0

其中cond是您要检查的条件。

答案 1 :(得分:0)

我觉得在F#中2D阵列有点尴尬,但是你可以这样做:

let recursivelyCountID ID (matr : 'T[,]) =
    let rec dim1 acc index0 index1 =
        if index1 > matr.GetUpperBound 1 then
            acc
        else
            let newAcc = if matr.[index0, index1] = ID then acc+1 else acc
            dim1 newAcc index0 (index1+1)

    let rec dim0 acc index0 =
        if index0 > matr.GetUpperBound 0
        then acc
        else dim0 (acc + (dim1 0 index0 0)) (index0+1)

    dim0 (matr.GetLowerBound 0) (matr.GetLowerBound 1)

如果您改用阵列数组,可以使用F#标准阵列模块中的函数:

let IDsInInnerArray ID xs = xs |> Array.sumBy (fun i -> if i = ID then 1 else 0)
let totalIDs ID xss = xss |> Array.map (fun xs -> IDsInInnerArray ID xs) |> Array.sum

编辑:由于错过了2D数组实现IEnumerable这一事实,我感到很尴尬,因此,对于2D数组的直接函数,不是使用以前的代码,而是使用数组的数组:

let totalIDs ID (matr : 'T[,]) = 
    matr 
    |> Seq.cast<'T> 
    |> Seq.sumBy (fun i -> if i = ID then 1 else 0)

...使用Seq.cast函数作为scrwtp在他的回答中显示。

答案 2 :(得分:0)

有点笨重:

 let count (x : 'a [,]) (e : 'a) =
    seq { for x in arr do yield x :?> 'a } |> Seq.where ((=) e) |> Seq.length

Arrays实现了GetEnumerator,因此这也适用于Array3D和4D。