2

I have a function that works fine for lists however the input to the function comes as float[,] from external system / language.

I read this but when I apply this I get an error float[,] is not compatible with Seq<a'>. However this list is also only of floats.

List function:

let aggrArraysL data =
    data
    |> Seq.groupBy (fun (a, b, c) -> a)
    |> Seq.map (fun (key, group) ->
        group |> Seq.reduce (fun (a, b, c) (x, y, z) -> a, b + y, (b * c + y * z * 1.)/(b + y)))

Array attempt:

let aggrArrays (data2 : float[,]) =
    data2
    |> Seq.toList
    |> Seq.groupBy (fun (a, b, c) -> a)
    |> Seq.map (fun (key, group) ->
        group |> Seq.reduce (fun (a, b, c) (x, y, z) -> a, b + y, (b * c + y * z * 1.)/(b + y)))
    |> Seq.toArray

Where am I going wrong? thanks!

Community
  • 1
  • 1
nik
  • 1,672
  • 2
  • 17
  • 36

1 Answers1

4

2D arrays implement IEnumerable so you can just cast them using Seq.cast<T>:

let toList (data2: float[,]) = data2 |> Seq.cast<float> |> Seq.toList

You probably want to make it generic:

let toList<'a> (data2: 'a [,]) = data2 |> Seq.cast<'a> |> Seq.toList

EDIT: It looks like you want to map the array into a list of row elements instead of flattening it. In this case you could do:

let aggrArrays (data2:float[,])  =
    [0 .. (Array2D.length1 data2) - 1]
    |> List.map (fun i -> (data2.[i, 0], data2.[i, 1], data2.[i, 2]))
    |> Seq.groupBy id
    |> Seq.map (fun (key, group) -> group |> Seq.reduce (fun (a,b,c) (x, y, z) -> a, b+y , (b*c+y*z*1.)/(b+y)))
    |> Seq.toArray
Lee
  • 142,018
  • 20
  • 234
  • 287
  • thanks Lee. I tried this also but now I m getting an error in the Seq.groupby statement. Again type mismatch – nik Oct 13 '13 at 18:01
  • @nik - The function you pass to `Seq.groupBy` takes a single argument of type `'T`, which in your case will be a `float`. You are matching on a tuple with 3 elements. If you want to group all elements with the same value you can just group by `id`. – Lee Oct 13 '13 at 18:05
  • I want to group all elements with the same value in Column 1, and then do some arithmetic on the elements in each group (col 2 & 3), sum, weighted average, etc – nik Oct 13 '13 at 18:13
  • @nik - Ok I've updated the answer to map the rows instead, is that what you need? – Lee Oct 13 '13 at 18:35
  • thanks Lee but somehow this only returns the first row of data2:float[,]. Does this flatten in the wrong dimension? – nik Oct 13 '13 at 19:03
  • @nik - Sorry, it should use `Array2D.length1` to get the number of rows, not `base1`. I've updated the answer. – Lee Oct 13 '13 at 19:28