Array initialization in F# - arrays

How do I create and initialize an array in F# based on a given record type?
Suppose I want to create an Array of 100 record1 records.
e.g.
type record1 = {
value1:string;
value2:string
}
let myArray = Array.init 100 ?
But it appears the Array.init does not allow for this, is there a way to do this?
Edited to add:
Of course I could do something like this:
let myArray = [|for i in 0..99 -> { value1="x"; value2="y" }|]

You can use also Array.create, which creates an array of a given size, with all its elements initialized to a defined value:
let myArray = Array.create 100 {value1="x"; value2="y"}
Give a look to this list of array operations.

This should do what you need. Hope it helps.
type record1 = {
value1:string;
value2:string
}
let myArray = Array.init 100 (fun x -> {value1 = "x"; value2 = "y"})
or using Generics
let myArray = Array.init<record1> 100 (fun x -> {value1 = "x"; value2 = "y"})

Or you can create a sequence, instead of creating an array, like this:
// nItems, given n and an item, returns a sequence of item repeated n times
let rec nItems n item =
seq {
match n with
| n when n > 0 -> yield item; yield! nItems (n - 1) item
| _ -> ()
}
type Fnord =
{ foo: int }
printfn "%A" (nItems 99999999 {foo = 3})
// seq [{foo = 3;}; {foo = 3;}; {foo = 3;}; {foo = 3;}; ...]
printfn "%A" (nItems 3 3 |> Seq.toArray)
[|3; 3; 3|]
The nice thing about the sequence, instead of an array, is that it creates items as you need them, rather than all at once. And it's simple to go back and forth between sequences and arrays if you need to.

Related

F#: Array of n Empty Lists

I want to create an Array which contains n empty lists, but the compiler has some problems with the type.
Both
Array.create 5 []
and
[| for i in 1..5 -> [] |]
does not work. Does anyone have any ideas what´s wrong with my code?
I expect the following output:
[| []; []; []; []; [] |]
The reason I want to create such an Array is that I in the next step want to create lists step by step in the Array by appending elements to the empty lists.
Thx in advance
You need to add type annotations or F# cannot say what type of list [] has.
For example, create an array of int list like so:
> Array.create<int list> 5 [] ;;
val it : int list [] = [|[]; []; []; []; []|]
Or in a generic function:
> let foo<'t> n = Array.create<(int * 't) list> n ;;
val foo : n:int -> ((int * 't) list -> (int * 't) list [])

Assign variable to array element where variable and array can be modified independently in ocaml

Here is the problem I can't get around, I'm working in ocaml to copy the elements of an array to a new array. I want to be able to modify these arrays independently from each other, but no matter what I try, a change to one array is reflected in the other array as well.
Here is a simplified example:
type sampleType = { a : int; b : int array };;
let x = {a = 5; b = [|1, 2, 3|] };;
let y = x.b;;
Array.set y 1 6;;
After running these commands I want:
y - : int array = [|1; 6; 3|]
x - : sampleType = {a = 5; b = [|1; 2; 3|]}
Instead x is being changed along with y, and
x - : sampleType = {a = 5; b = [|1; 6; 3|]}
Any solutions to this problem?
As you see from your experiments, this code:
let y = x.b
makes y refer to the very same array as x.b. It doesn't create an independent array. To create an independent array, you need to copy:
let y = Array.copy x.b
I was specifically using 3d arrays, realized I had to apply Array.copy at the lowest level of the 3d array, rather than at the top level.
let arr = Array.init 3 (fun _ -> Array.init 3 (fun _ -> (Array.init 3 (fun _ -> {faces = [|0;1;2;3;4|]}))));;
let drr = Array.init 3 (fun i -> Array.init 3 (fun j -> Array.copy arr.(i).(j)));;
This gave me the result I needed.

How to get the first index of a given element in Array/List in Elm?

In Javascript, one could use indexOf to get the first instance of a given element in an array.
What's the best way to do this in Elm?
array = Array.fromList ["Stack","Overflow","is","","awesome"]
element = ""
indexOf element array =
-- should return 3
What if we have a list instead of an array?
There is a third party module elm-list-extra that provides this function. "elemIndex" (works for 0.19).
And this one for < 0.19 elemIndex
Just for fun, here's a hand-rolled version for List:
helper : List a -> a -> Int -> Int
helper lst elem offset =
case lst of
[] -> -1
x :: xs ->
if x == elem then offset
else helper xs elem (offset + 1)
indexOf lst element =
helper lst element 0
helper recursively searches the list for the element, keeping track of the number of elements we've visited so far. For the empty list, it returns -1.
If you don't like magic constants, you could easily change the return type to Maybe Int and return Nothing instead.
And here's a complete program using it (just copy + paste into the online REPL at elm-lang.org:
import Html exposing (text)
lst = ["Stack","Overflow","is","","awesome"]
element = ""
helper : List a -> a -> Int -> Int
helper lst elem offset =
case lst of
[] -> -1
x :: xs ->
if x == elem then offset
else helper xs elem (offset + 1)
indexOf lst element =
helper lst element 0
main =
text (toString (indexOf lst ""))
Another take, composing core library functions. I find this more readable than recursion, and more declarative; it's just a straightforward pipeline of data transformations. The data structure is the last parameter, so that you can partially apply the value that you're looking for, like idxOfFoo = firstIndexOf "foo".
indicesOf : a -> List a -> List Int
indicesOf thing things =
things
|> List.indexedMap (,)
|> List.filter (\(idx, item) -> item == thing)
|> List.map fst
firstIndexOf : a -> List a -> Int
firstIndexOf thing things =
indicesOf thing things
|> List.minimum
|> Maybe.withDefault -1
lastIndexOf : a -> List a -> Int
lastIndexOf thing things =
indicesOf thing things
|> List.maximum
|> Maybe.withDefault -1
REPL session:
> things = ["foo", "bar", "bat", "foo", "baz"]
["foo","bar","bat","foo","baz"] : List String
>
> firstIndexOf "foo" things
0 : Int
>
> lastIndexOf "foo" things
3 : Int
>
At a glance, I think this is similar in complexity to CircuitHub's implementation in List.Extra.
Code
indexOf : a -> Array a -> Int
indexOf element array =
let
item =
array
|> Array.toIndexedList
|> List.filter (\tuple -> isElement tuple element)
|> List.head
in
case item of
Just value ->
Tuple.first value
Nothing ->
-1
isElement : (Int, a) -> a -> Bool
isElement tuple element =
Tuple.second tuple == element
Usage
list =
[ "a"
, "b"
, "c"
]
index =
list
|> Array.fromList
|> indexOf "b"

F# Finding the Missing element between 2 arrays/lists

`So, I am very new to F#. I hope the issue is simple. I have been doing research and looking around. I have an "Incomplete structured construct at or before this point in expression" error. I feel like it might be something simple or I am way off.
The objective is:
There is an array of non negative integers. A second array is
formed by shuffling the elements of the first
array and deleting a random element. Given these two arrays, find which element is missing in the second
array. Linear searching is not allowed.
let FindMiss list =
match list with
| [] ->
[]
|firstElem::otherElements ->
let rand = new Random
let shuffle (arr : 'a array) =
let array = Array.copy arr
let n = array.Length
for x in 1..n do
let i = n-x
let j = rand.Next(i+1)
let tmp = array.[i]
array.[i] <- array.[j]
array.[j] <- tmp
array
return array
array.[rand].delete
|array::list ->
let d=collections.defaultdict(int)
for num in list do
d[num] +=1
for num in array1 do
if d[num]==0 then return num
else d[num]-=1
printfn "The missing Number is: %A" (FindMiss[4;2;1;7;5;6;3;2])
The task is to reimplement List.except?
If not, just use that 'except' then:
[1;2;3] |> List.except [1;2]
Or was the task "random removal of element in list"? Then this is "the answer": https://stackoverflow.com/a/2889972/5514938
For a start, for more readability, you can take the shuffling and deleting a random element in a separate function. For arrays, they may look like this:
let Shuffle arr =
let rand = System.Random()
arr |> Array.sortBy(fun _ -> rand.Next())
let RemoveRandom arr =
let rand = System.Random()
let lng = arr |> Array.length
let index = rand.Next lng
[|0..lng - 1 |]
|> Array.choose(fun x -> if x = index then None else Some(arr.[x]))
|> Shuffle
Further define the search function:
let FindMiss arr1 arr2 =
let sum1 = arr1 |> Array.sum
let sum2 = arr2 |> Array.sum
sum1 - sum2
Example:
let first = [| 4;2;1;7;5;6;3;2 |]
first |> printfn "%A"
let second = first |> RemoveRandom
second |> printfn "%A"
FindMiss first second |> printfn "Missing value is %i"
Print:
[|4; 2; 1; 7; 5; 6; 3; 2|]
[|2; 2; 3; 7; 1; 5; 6|]
Missing value is 4
Link:
https://dotnetfiddle.net/g6wKUX

What is the immutable version to de/reference array?

How to de/reference the 3 array variables in this code instead of using mutable values?
The code below computes the Longest common subsequence (LCS) by diagonal traversing the m*n array.
The arguments are 2 char arrays like so:
So LCS method should result to length 4 as the longest common sub-sequence chars are "acbb" & "bcbb".
let private s1 = "ABCDBB".ToCharArray()
let private s2 = "CBACBAABA".ToCharArray()
let public lcs_seq_1d_diags (x:char[]) (y:char[]) =
let m = x.Length
let n = y.Length
let mutable dk2 = Array.create (1+m) 0
//printfn "\r\n0: %A" dk2
let mutable dk1 = Array.create (1+m) 0
//printfn "1: %A" dk1
let mutable dk = Array.create (1+m) 0
for k = 2 to m+n do
let low = max 1 (k-m)
let high = min (k-1) n
for j = low to high do
let i = k - j
if x.[i-1] = y.[j-1] then
dk.[i] <- dk2.[i-1] + 1
else
dk.[i] <- max dk1.[i] dk1.[i-1]
let mutable temp = dk2
dk2 <- dk1
dk1 <- dk
dk <- temp
dk1.[m]
let private res_seq_1d_rows = duration (fun () -> lcs_seq_1d_rows s1 s2)
//res_seq_1d_rows = 4
Take a look at the reference cells http://msdn.microsoft.com/en-us/library/dd233186.aspx
The syntax looks like this:
let a = ref 1 // declaring a reference
a := 2 // changing the reference value
printfn "%i" !a // dereferencing
This might also be interesting: F#: let mutable vs. ref
Arrays are mutable by default. Try using a list instead if you want immutability.
Try starting with this instead:
let s1 = List.ofSeq "ABCDBB"
let s2 = List.ofSeq "CBACBAABA"
The rest I leave as an exercise for the reader :-)

Resources