这是一个相当简单的请求,但我在使用F#的语法时遇到了问题。我需要创建一个函数来递归迭代二维数组,每次满足条件时增加一个计数器。在这种情况下,该函数将ID作为参数,然后检查内部数组中ID的存在次数。我在考虑这样的事情:
let runner array count =
match count with
|0 -> (exit loop)
|n -> (perform function)
runner array count-1
对于递归迭代函数的一般结构。但是,有几点我不确定。在F#中退出递归循环(即基本情况)的条件是什么?我如何构建它,以便它遍历主数组和子数组以检查ID?假设我不能使用可变函数,那么如何使计数器随着递归循环的每次运行而增加?任何帮助将不胜感激。
答案 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。