Convert list to Array2D - f#

I'm trying to convert a single list to a multi-dimensional Array2D. Basically go from [1; 2; 3] to [[1; 2; 3]]. I can't just use List.toArray as I'm using an API function which takes an int[,] as one of its inputs.
What's the best way to do this?

Just nest the list within another list:
array2D [[1; 2; 3]]
> val it : int [,] = [[1; 2; 3]]

Related

Implement insert in f# elements into set returning the new set with elements?

I'm trying to write a function in F# that inserts y into S, where y and S are sets of elements, in the returning set S elements should be inserted in order using <, if x exists in S then S is returned unchanged. I hope this is much clear. I have implemented the function as follows
let rec insert x S =
match S with
|[] -> x
|e::rest -> e::(insert x rest)
but it does not give me expected output. For example if
S = [2; 3]
x = [3; 4]
the output should be
[2; 3; 4]
But I'm getting
[2; 3; 3; 4]

Does F# have a foldList function?

Mathematica and perhaps other languages have a foldList function. It is very much like fold but instead of returning only the final computed value it returns every intermediate value.
It is not hard to write a foldList function in F#:
let foldList f (x: 'S) (m: list<'T>) =
let fs (xs: list<'S>) (y: 'T) = (f (Seq.head xs) y)::xs
List.fold fs [x] m
|> List.rev
let m = [1; 2; -3; 5]
foldList (+) 0 m
// val it : int list = [0; 1; 3; 0; 5]
List.fold (+) 0 m
// val it : int = 5
Is there such a function in F#?
If not, is there a more efficient implementation than the one above?
Is there a way to avoid the call to List.rev?
Yes, this is a built-in function, it's called List.scan:
let m = [1; 2; -3; 5]
List.scan (+) 0 m;;
//val it : int list = [0; 1; 3; 0; 5]
To answer your question about reversing the list, the implementation in FSharp.Core avoids reversing the list by using mutation. This mutable API is not exposed publicly. You can find the source code here if you're interested.

Slicing in a 2D Array in F# but similar to Matlab?

I was wondering if there is a way to use a list or an array of int as an index for slicing into a array to get a sub array in f#.
I know you can do the following
Arr2d.[*,1] or Arr2d.[1..5,1..2] etc...
But I was looking for something like in Matlab where you can write:
Arr2d([1;6;10],1) or Arr2d(1:10,[1;6;10])
Is it possible to do slicing like that in F#?
Thanks!
Here was my sample solution: (maybe not optimal but works)
let sampleMatrix = Array2D.init 10 5 (fun x y -> y)
val sampleMatrix : int [,] = [[0; 1; 2; 3; 4]
[0; 1; 2; 3; 4]
[0; 1; 2; 3; 4]
[0; 1; 2; 3; 4]
[0; 1; 2; 3; 4]
[0; 1; 2; 3; 4]
[0; 1; 2; 3; 4]
[0; 1; 2; 3; 4]
[0; 1; 2; 3; 4]
[0; 1; 2; 3; 4]]
let idxlist = [1;3;4]
let array2dColumnSlice (idxlist:list<int>) (data:'T[,]) =
let tmp = [|for i in idxlist -> data.[*,i]|]
Array2D.init tmp.[0].Length tmp.Length (fun x y -> tmp.[y].[x] )
let slice = array2dColumnSlice idxlist sampleMatrix
val slice : int [,] = [[1; 3; 4]
[1; 3; 4]
[1; 3; 4]
[1; 3; 4]
[1; 3; 4]
[1; 3; 4]
[1; 3; 4]
[1; 3; 4]
[1; 3; 4]
[1; 3; 4]]
As detailed here, there is no additional slicing notation beyond what you have already found.
For ranges only, it is possible, by wrapping Array2D with a sliceable type, or using the old PowerPack's Matrix type.
See the docs here:
http://msdn.microsoft.com/en-us/library/dd233214.aspx#sectionToggle6
You can use this slicing syntax for types that implement the element
access operators and overloaded GetSlice methods. For example, the
following code creates a Matrix type that wraps the F# 2D array,
implements an Item property to provide support for array indexing, and
implements three versions of GetSlice. If you can use this code as a
template for your matrix types, you can use all the slicing operations
that this section describes.

Type inference with List.fold

I'm having some issues transforming a list of lists again. I have a list of list of ints it looks like this.
val p5PrimeFactorization : int list list =
[[1]; [2]; [3]; [2; 2]; [5]; [3; 2]; [7]; [2; 2; 2]; [3; 3]; [5; 2]; [11];
[3; 2; 2]; [13]; [7; 2]; [5; 3]; [2; 2; 2; 2]; [17]; [3; 3; 2]; [19];
[5; 2; 2]]
Now I want to transform each list into the product of all entries. Now this works
[for n in 2..20 -> primeFactors n 2 []]
|> List.map (List.sum)
But this doesn't..
[for n in 2..20 -> primeFactors n 2 []]
|> List.map (List.fold (fun acc elem -> acc * elem))
It seems the problem is that it infers the type of acc and elem to be of type int list which isn't right. I don't understand why List.sum which basically does the same thing except it returns the sum of all numbers, works, but my folder will not.
In your second example, you haven't specified the initial value for the fold.
You probably meant something like
|> List.map (List.fold (fun acc elem -> acc * elem) 1)

FSharp Compound List

What's the cleanest & simplest way to create this 'compound' list in F#?
Input:
[ 1; 2; 3; 4; 5 ]
Desired Output:
[ [1]; [1;2]; [1;2;3]; [1,2,3,4]; [1;2;3;4;5] ]
There are many ways but I think this is a clean one:
[1;2;3;4;5]
|> List.scan (fun x y -> x # [y]) []
|> List.tail
using List.scan and finally List.tail to omit the first element which is an empty list.
Here's another way interpreting the contents strictly as ints and using list comprehension:
[1; 2; 3; 4; 5] |> List.map(fun n -> [ for i = 1 to n do yield i ])
And you get the same output as above, but if your input is this:
[2; 1; 2] |> List.map(fun n -> [ for i = 1 to n do yield i ])
You get:
[[1; 2]; [1]; [1; 2]]
Which may or may not be what you want.

Resources