# Recursively iterating over an array in F #

This is a pretty basic query, but I'm having trouble with the F # syntax. I need to create a function to iterate over a two-dimensional array recursively, incrementing a counter every time a condition is met. In this case, the function takes an identifier as a parameter and then checks how many times that identifier is present inside the internal arrays. I was thinking about something like this:

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

```

For the general structure of a recursive iteration function. However, there are a few things that I'm not sure about. What are the conditions for breaking out of a recursive loop (i.e. Base case) in F #? How can I structure this so that it crosses over both the main and sub-range in order to check the ID? And how do I do this so that the counter increments with each iteration of the recursive loops, assuming I cannot use mutable functions? Any help would be appreciated.

+1

source to share

There is a more general way to do this. You want to dump the 2d array. They don't have a fold defined in the Array2D module, but you can write one.

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

```

We're cheating a little here, casting gives us a flat sequence of elements from the array, which we later turn into a regular fold. So now you can do:

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

```

where cond is the condition you want to check.

+2

source

I find 2D arrays a little awkward in F #, but here's how you could do it:

``````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)
```

```

If you use an array of arrays instead, you can use functions in the standard F # module:

``````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
```

```

Edit: I was confused not noticing that 2D arrays implement IEnumerable, so instead of the previous code working with arrays of arrays, the direct function for 2D arrays would be:

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

```

... using the Seq.cast function, as scrwtp shows in his answer.

0

source

This is a little awkward:

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

```

Arrays implement GetEnumerator, so this should work for Array3D and 4D as well.

0

source

All Articles