Reputation: 1784
I have asked this question before in c# here and there wasnt really a succinct way of doing this. I m now trying to do the same in fsharp and see how that goes.
I have two arrays that are same length and type and I would like to combine them into one with same length and 2 columns. I have this code that does this:
let twoDimensionalArray (arr1:array<'a>) (arr2:array<'a>) =
let rws = arr1|> Array.length
Array2D.init rws 1 (fun i j -> arr1.[i], arr2.[i])
To be honest this surprises me a bit as I would have thought there should be a 2 in the column dimension like this:
Array2D.init rws 2 (fun i j -> arr1.[i], arr2.[i])
but if I change this to 2 then I get this:
val it : (float * float) [,] = [[(1.0, 3.0); (1.0, 3.0)]
[(2.0, 4.0); (2.0, 4.0)]]
for this data:
let arr1 = [| 1.0; 2.0 |]
let arr2= [|3.0; 4.0 |]
Why?
Also I would really like to write this more generacally, so if the first array has 2 columns and the second 1, I get a 3 column matrix and so forth. I tried this:
let MultiArray (arr1:array<'a>) (arr2:array<'a>) =
let rws = arr1.Length
let c1 = arr1.GetLength(1)
let c2 = arr2.GetLength(1)
let cols = c1+c2
Array2D.init rws cols (fun i j -> arr1.[i], arr2.[i])
But this is flawed.
Could you please let me know how I could do this? Also why my first function works but I think is wrong?
Thanks
Thanks John! Working solution:
let MultiArray (inp:float[][]) =
let cls = inp |> Array.length
let rows = inp.[0] |> Array.length
Array2D.init rows cls (fun i j -> inp.[j].[i])
Sample data and use:
let arr1 = [|1.0 ; 4.0; 6.0;5.;8.|]
let arr2= [|7.0; 8.0; 9.0;9.;10. |]
let inp = [| arr1; arr2; arr1|]
MultiArray inp;;
val it : float [,] = [[1.0; 7.0; 1.0]
[4.0; 8.0; 4.0]
[6.0; 9.0; 6.0]
[5.0; 9.0; 5.0]
[8.0; 10.0; 8.0]]
Upvotes: 0
Views: 979
Reputation: 1
Nice Solution; Would suggest to change this lines to:
let c1 = arr1.GetLength(0)
let c2 = arr2.GetLength(0)
In my case I got an index out of bound with 1 as described above.
However I prefer 'generica' as well:
Array2D.init count rows (fun i j -> inp.[j].[i])
Upvotes: -1
Reputation: 25516
So the reason for the unexpected version of the first code is you are creating a 2D array of tuples - rather than a 2D array of values. You actually should set the size of the first dimension to 1 in this case as the second dimension is hiding in the fact that the tuple has more variables.
A simple version which creates an actual 2D array would be
Array2D.init rws 2 (fun i j ->match j with |0 -> arr1.[i] |1 -> arr2.[i])
A more generic version would take in an array of arrays as input like so
let MultiArray (inp:float[][])
let count = inp |> Array.length
let rows = inp.[0] |> Array.length
Array2D.init count rows (fun i j -> inp.[j].[i]
Upvotes: 3