f#: initialize array of array - f#

in the following code, does array of array A = B?
let A = Array.init 3 (fun _ -> Array.init 2 (fun _ -> 0))
let defaultCreate n defaultValue = Array.init n (fun _ -> defaultValue)
let B = defaultCreate 3 (defaultCreate 2 0)
if I assign values to A and B, they are different ,what happened? thanks.
for i = 0 to 2 do
for j = 0 to 1 do
A.[i].[j] <-i + j
B.[i].[j] <-i + j
printfn "%A vs %A" A B
A = [|[|0; 1|]; [|1; 2|]; [|2; 3|]|] and B = [|[|2; 3|]; [|2; 3|]; [|2; 3|]|]

let B = defaultCreate 3 (defaultCreate 2 0)
You create an array and then you use this array as values for each cell.
It's as if you did something like this:
let a = [|1; 2; 3; 4|]
let b = [|a; a; a; a|]
The same array a is used for every cell (think pointer to a is you're used to C). Thus, modifying b.[0].[1] will change every a.[1].
In my sample:
> b.[0].[1] <- 10;;
val it : unit = ()
> b;;
[|[|1; 10; 3; 4|]; [|1; 10; 3; 4|]; [|1; 10; 3; 4|]; [|1; 10; 3; 4|]|]
The same thing happens with your code.

They are not the same.
Arrays are reference types, and are stored on the heap. When you create an array with another array as the default value, you are storing references to the same array, over and over again.
Numbers are another thing. They are immutable, and are stored by value, on the stack. So you can't change the value of 1 to anything other than 1.
To create an "jagged" array, you need to call Array.init from inside the initializer to the first Array.init call, to create new arrays for each slot.
Also; You could use Array.create if you do want to have the same value in every slot. Be careful about reference types though.
let A = Array.init 3 (fun _ -> Array.create 2 0)

Related

Can I directly use a tuple as an Array2D index in F#?

Lets say I have an the following Array2D
> let arr = Array2D.init 2 3 (fun i j -> (i+1) * (j+2));;
> printfn "%A" arr
[[2; 3; 4]
[4; 6; 8]]
I know I can access an array element like so
> arr[1, 2];;
8
But what if I have the coordinates saved in a tuple. Why can't I do the following or something similar:
> let coord = (1, 2);;
> arr[coord]
Error: input.fsx (2,1)-(2,11) typecheck error This expression was expected to have type
''a[]'
but here has type
'int[,]'
It feels kinda stupid to unpack the tuple each time before using it. Or is this the only way?
> let x, y = coord;;
> arr[x, y];;
8
You could always use ||> to unpack the tuple rather than using let expressions, along with Array2D.get. The downside is that its a lil more verbose for sure.
- let arr = Array2D.init 2 3 (fun i j -> (i+1) * (j+2))
- let coord = (1,2)
- coord ||> Array2D.get arr;;
val it : int = 8
I don't think there's any direct way to index a 2D array using a tuple. One similar alternative is to use a Map instead:
let map =
seq {
for i = 0 to 1 do
for j = 0 to 2 do
yield (i, j), (i+1) * (j+2)
} |> Map
let coord = (1, 2)
map[coord] // 8
F# treats tupled arguments in a special way. If method is defined not in F#, then it's arguments should be tupled:
System.String.Join(", ", [|1; 2; 3|])
System.String.Join ", " [|1; 2; 3|] // not valid
It's done to help overload resolution.
What you can do is to extend multidimensional array type:
type ``[,]``<'a> with
member inline ar.Item with get ((x, y): (int*int)) : 'a =
ar.[x, y]
And then use it:
let coord = (1, 2)
arr.Item coord |> printfn "%d"
Unfortunately arr.[coord] is not available and looks like a bug in compiler
All problems are solved through functions!
let xss = Array2D.init 2 3 (fun i j -> (i+1) * (j+2));;
let get arr (x,y) = Array2D.get arr x y
get xss (1,2) (* Returns 8 *)

Is it possible to repeat an array?

I need to add 1 to each element in an array, and if it goes out of range, I need to start over.
let arr = [| 1; 2; 3 |]
for i = 0 to Array.length arr - 1 do
arr.[i] <- arr.[i] + 1
printfn "i %A" (arr.[i])
I want to add 5 points to the array, so that it iterates over the array and gives one point in each element, so the array would partially be [| 2; 3; 4 |] and iterate through the array again and end up being arr = [| 3; 4; 4 |]
Actually you can calculate exactly how much you should add to each element of array. So you can solve the problem by going through the array in only one time.
let addPoints arr points =
let len = arr |> Array.length
let added = points / len
let extraCount = points % len
arr
|> Array.mapi (fun i x ->
if i < extraCount then x + added + 1
else x + added)
addPoints [| 1; 2; 3 |] 5
|> printfn "%A" // [|3; 4; 4|]
Mutating the array or not, it's up to you.
Rather than mutating the array, a more idiomatic F# approach is to create a new array with the newly calculated results. You can use the built-in Array.map function to do apply the same transformation to each element of the array. To increment all by one, you can write:
let arr = [| 1; 2; 3 |]
arr |> Array.map (fun v -> v + 1)
If you want to restrict the maximal value to 4, you'll need to do that in the body of the function, i.e. v + 1. To make it easier to do this repeatedly, it's helpful to define a function.
let step arr =
arr |> Array.map (fun v -> min 4 (v + 1))
Here, step is a function you can call to do one step of the transformation. min 4 (v + 1) ensures that when v + 1 is more than 4, you get just 4 as the result. Now you can run step repeatedly using |>:
let arr1 = arr |> step
let arr2 = arr |> step |> step
I agree with #TomasPetricek in that the way to go should be to create new arrays using map. However, if you must mutate the array, the following loop-based approach should work just fine:
let incArrayElements n (a : _ []) =
let rec loop k i =
if k > 0 then
a.[i] <- a.[i] + 1
let ii = i + 1
if ii >= a.Length then 0 else ii
|> loop (k - 1)
if n > 0 then loop n 0
If required, this can also be easily modified to include a parameter for the starting index.

Why does this definition returns a function?

I found the following in the book Expert F# 4.0, Fourth Edition, by Don Syme, Adam Granicz, and Antonio Cisternino:
let generateStamp =
let mutable count = 0
(fun () -> count <- count + 1; count)
I could not understand why this code creates a function:
val generateStamp : (unit -> int)
It looks to me like its signature should be
val generateStamp : int
For example, the following code:
let gS =
let mutable count = 0
(printfn "%d" count; count)
creates an int value:
val gS : int = 0
As I understand it the code (fun () -> count <- count + 1; count) should first evaluate the lambda and then count. So the value of generateStamp should be just count, as it is in the definition of gS. What am I missing?
In any block of F# code, the last expression in that block will be the value of that block. A block can be defined in one of two ways: by indentation, or with ; between the block's expressions.
The expression fun () -> other expressions here creates a function. Since that's the last expression in the code block under let generateStamp =, that's the value that gets stored in generateStamp.
Your confusion is that you think that the expressions inside the fun () are going to be evaluated immediately as part of the value of generateStamp, but they're not. They are defining the body of the anonymous function returned by the fun () expression. You're absolutely right that inside that block of code, count is the last expression and so it's the thing returned by that function. But the fun () expression creates a function, which will only evaluate its contents later when it is called. It does not evaluate its contents immediately.
By contrast, the expression (printfn "%d" count; count) is a block of code with two expressions in it. It is not a function, so it will be immediately evaluated. Its last expression is count, so the value of the code block (printfn "%d" count; count) is count. Since the (printfn "%d" count; count) block is being evaluated immediately, you can mentally replace it with count. And so the value of gS is count, whereas the value of generateStamp is a function that will return count when it's evaluated.
It's syntactic trickery. The last ; count part is actually part of the lambda, not the next expression after it.
Here are some simplified examples to work through:
let x = 1; 2; 3 // x = 3
let f x = 1; 2; 3 // f is a function
let y = f 5 // y = 3, result of calling function "f"
let f = fun x -> 1; 2; 3 // Equivalent to the previous definition of "f"
let y = f 5 // y = 3, same as above
let f =
fun x -> 1; 2; 3 // Still equivalent
let y = f 5 // y = 3, same as above
let f =
let z = 5
fun x -> 1; 2; 3 // Still equivalent
let y = f 5 // y = 3, same as above
// Your original example. See the similarity?
let generateStamp =
let mutable count = 0
fun () -> count <- count + 1; count
Now, if you wanted to have count be the return value of generateStamp, you'd need to put it either outside the parens or on the next line:
// The following two definitions will make "generateStamp" have type "int"
let generateStamp =
let mutable count = 0
(fun () -> count <- count + 1); count
let generateStamp =
let mutable count = 0
(fun () -> count <- count + 1)
count

Combine data into smaller discrete intervals

Suppose we have a pair of input arrays, or a list of (key, value) tuples if you prefer. What's an elegant and performant way to combine values that have indices falling in a certain interval? For example, if the interval (or 'bin') size is 10 then the values of all indices from 0 < x <= 10 would be combined, as would the values of indices from 10 < x <= 20 and so on. I want:
let interval = 10
let index = [| 6; 12; 18; 24 |]
let value = [| a; b; c; d |]
result = [| a; b + c; d |]
The crudest way to do this would be to use a whole lot of if, else if statements (the index range has a defined upper limit). I got close with
for i = 0 to index.Length do
result.[Math.Floor(index.[i]/10] += value.[Math.Floor(index.[i]/10]
but this is doing 0 <= x < 10, not 0 < x <= 10.
I also tried assuming the indices are ordered and evenly spaced, with
for i = 1 : ( index.Length - 1 ) / valuesPerBin
valueRange = ((i-1)*valuesPerBin + 1) : i*valuesPerBin )
result(i) = sum(value(valueRange))
which is nice but obviously breaks if there is a non integer number of values per bin.
What's the best way of doing this in F#? Is there a name or an existing function for what I'm trying to do?
let interval = 10
let index = [6;12;18;24]
let value =[101;102;103;104]
let intervals = List.map (fun e -> e/interval) index
let keys = List.map2(fun e1 e2 -> (e1,e2)) intervals value
let skeys = Seq.ofList keys
let result = skeys
|>Seq.groupBy (fun p -> fst p)
|>Seq.map (fun p -> snd p)
|>Seq.map(fun s -> Seq.sumBy (fun p -> snd p) s)
result will be [101;205;104] (as a Seq).
If you want to convert to an array, apply Seq.toArray.
Is it what you wanted ?
Adapt the surrounding code to use
0 <= x < 10 instead of 0 < x <= 10. In my case this was just a simple definition change in another function, allowing me to use
for i = 0 to index.Length do
result.[Math.Floor(index.[i]/10] += value.[Math.Floor(index.[i]/10], which is much simpler and terser syntax than the alternatives.

In F#, is there a functional way to converting a flat array of items into an array of a group of items?

In F#, imagine we have an array of bytes representing pixel data with three bytes per pixel in RGB order:
[| 255; 0; 0; //Solid red
0; 255; 0; //Solid green
0; 0; 255; //Solid blue
1; 72; 9;
34; 15; 155
... |]
I'm having a hard time knowing how to functionally operate on this data as-is, since a single item is really a consecutive block of three elements in the array.
So, I need to first group the triples in the array into something like this:
[|
[| 255; 0; 0 |];
[| 0; 255; 0 |];
[| 0; 0; 255 |];
[| 1; 72; 9 |];
[| 34; 15; 155 |]
... |]
Now, gathering up the triples into sub-arrays is easy enough to do with a for loop, but I'm curious--is there a functional way to gather up groups of array elements in F#? My ultimate goal is not simply to convert the data as illustrated above, but to solve the problem in a more declarative and functional manner. But I have yet to find an example of how to do this without an imperative loop.
kvb's answer may not give you what you want. Seq.windowed returns a sliding window of values, e.g., [1; 2; 3; 4] becomes [[1; 2; 3]; [2; 3; 4]]. It seems like you want it split into contiguous chunks. The following function takes a list and returns a list of triples ('T list -> ('T * 'T * 'T) list).
let toTriples list =
let rec aux f = function
| a :: b :: c :: rest -> aux (fun acc -> f ((a, b, c) :: acc)) rest
| _ -> f []
aux id list
Here's the inverse:
let ofTriples triples =
let rec aux f = function
| (a, b, c) :: rest -> aux (fun acc -> f (a :: b :: c :: acc)) rest
| [] -> f []
aux id triples
EDIT
If you're dealing with huge amounts of data, here's a sequence-based approach with constant memory use (all the options and tuples it creates have a negative impact on GC--see below for a better version):
let (|Next|_|) (e:IEnumerator<_>) =
if e.MoveNext() then Some e.Current
else None
let (|Triple|_|) = function
| Next a & Next b & Next c -> Some (a, b, c) //change to [|a;b;c|] if you like
| _ -> None
let toSeqTriples (items:seq<_>) =
use e = items.GetEnumerator()
let rec loop() =
seq {
match e with
| Triple (a, b, c) ->
yield a, b, c
yield! loop()
| _ -> ()
}
loop()
EDIT 2
ebb's question about memory use prompted me to test and I found toSeqTriples to be slow and cause surprisingly frequent GCs. The following version fixes those issues and is almost 4x faster than the list-based version.
let toSeqTriplesFast (items:seq<_>) =
use e = items.GetEnumerator()
let rec loop() =
seq {
if e.MoveNext() then
let a = e.Current
if e.MoveNext() then
let b = e.Current
if e.MoveNext() then
let c = e.Current
yield (a, b, c)
yield! loop()
}
loop()
This has relatively constant memory usage vs a list or array-based approach because a) if you have a seq to start with the entire sequence doesn't have to be slurped into a list/array; and b) it also returns a sequence, making it lazy, and avoiding allocating yet another list/array.
I need to first group the triples in the array into something like this:
If you know they will always be triples then representing then as a tuple int * int * int is more "typeful" than using an array because it conveys the fact that there are only ever exactly three elements.
Other people have described various ways to massage the data but I would actually recommend not bothering (unless there is more to this than you have described). I would opt for a function to destructure your array as-is instead:
let get i = a.[3*i], a.[3*i+1], a.[3*i+2]
If you really want to change the representation then you can now do:
let b = Array.init (a.Length/3) get
The answer really depends upon what you want to do next though...
(Hat tip: Scott Wlaschin) As of F# 4.0, you can use Array.chunkBySize(). It does exactly what you want:
let bs = [| 255; 0; 0; //Solid red
0; 255; 0; //Solid green
0; 0; 255; //Solid blue
1; 72; 9;
34; 15; 155 |]
let grouped = bs |> Array.chunkBySize 3
// [| [|255; 0; 0|]
// [| 0; 255; 0|]
// [| 0; 0; 255|]
// [| 1; 72; 9|]
// [| 34; 15; 155|] |]
The List and Seq modules also have chunkBySize() in F# 4.0. As of this writing, the docs at MSDN don't show chunkBySize() anywhere, but it's there if you're using F# 4.0.
UPDATE: As pointed out by Daniel, this answer is wrong because it creates a sliding window.
You can use the Seq.windowed function from the library. E.g.
let rgbPix = rawValues |> Seq.windowed 3
This returns a sequence rather than an array, so if you need random access, you could follow that with a call to Seq.toArray.
Another approach, that takes and yields arrays directly:
let splitArrays n arr =
match Array.length arr with
| 0 ->
invalidArg "arr" "array is empty"
| x when x % n <> 0 ->
invalidArg "arr" "array length is not evenly divisible by n"
| arrLen ->
let ret = arrLen / n |> Array.zeroCreate
let rec loop idx =
ret.[idx] <- Array.sub arr (idx * n) n
match idx + 1 with
| idx' when idx' <> ret.Length -> loop idx'
| _ -> ret
loop 0
Or, yet another:
let splitArray n arr =
match Array.length arr with
| 0 ->
invalidArg "arr" "array is empty"
| x when x % n <> 0 ->
invalidArg "arr" "array length is not evenly divisible by n"
| arrLen ->
let rec loop idx = seq {
yield Array.sub arr idx n
let idx' = idx + n
if idx' <> arrLen then
yield! loop idx' }
loop 0 |> Seq.toArray

Resources