Let's say that I want to do some in-array comparison in F#, e.g. determine whether a given integer array arr contains integers in strictly increasing order. I would do it like this:
let arri =
arr
|> Array.mapi (fun i e -> i, e)
let isArrStrictlyIncreasing =
arri
|> Array.tryFind (fun e ->
if fst e = arri.Length - 1 then
false
else
snd e >= snd arri.[1 + fst e])
|> Option.isNone
However, I am wondering if there is a more concise, "functional" way of making such in-array comparisons without the use of Array.mapi and if-else?
One simple way:
let isincr arr =
arr
|> Array.fold (fun (a,b) (c) -> ((b<c && a)),c) (true,System.Int32.MinValue)
|> fst
Couldn't you just do the following?
let expected = [| candidate.[0] .. candidate.[0] + candidate.Length - 1 |]
candidate = expected
This simply builds the array you'd expect, and uses F#'s Structural Equality to compare the two arrays.
A more general alternative might be this:
let isOrdered arr = arr |> Array.sort = arr
let hasDistinctMembers (arr : 'a array) =
let distinct = arr |> Seq.distinct |> Seq.toArray
distinct.Length = arr.Length
let isStrictlyIncreasing arr = arr |> isOrdered && arr |> hasDistinctMembers
Usage:
> isStrictlyIncreasing [| 7; 11; 8 |];;
val it : bool = false
> isStrictlyIncreasing [| 7..33 |];;
val it : bool = true
> isStrictlyIncreasing [| 7; 8; 11 |];;
val it : bool = true
> isStrictlyIncreasing [| 7; 7; 8; 11 |];;
val it : bool = false
Related
I have three arrays - first is a float array, second is a string array, and fltr is a string array. I need to generate a product of the elements in the first array filtered by whether the matching index in the second array contains all the characters in the elements of the filter array:
module SOQN =
open System
let first = [| 2.00; 3.00; 5.00; 7.00; 11.00 |]
let second = [| "ABCD"; "ABCE"; "ABDE"; "ACDE"; "BCDE" |]
let fltr = [| "AC"; "BD"; "CE" |]
let result =
first
|> Array.filter second // filter for elements containing characters in second array
|> Seq.reduce (fun x y -> x * y)
// Expected Result: let result = [| 42.00; 110.00; 231.00 |]
How do I generate the array of products?
Something like this
let first = [| 2.00; 3.00; 5.00; 7.00; 11.00 |]
let second = [| "ABCD"; "ABCE"; "ABDE"; "ACDE"; "BCDE" |]
let fltr = "AC"
Array.zip first second
|> Array.filter (fun (_, s) ->
Seq.forall (fun c -> s.Contains (string c)) fltr)
|> Array.map fst
|> Array.reduce (*)
The following snippet (though not idiomatic) provides the complete answer I was seeking and includes #xuanduc987 solution:
module SOANS =
open System
let first = [| 2.00; 3.00; 5.00; 7.00; 11.00 |]
let second = [| "ABCD"; "ABCE"; "ABDE"; "ACDE"; "BCDE" |]
let fltr = [| "AC"; "BD"; "CE" |]
let filterProduct (first:float[]) (second:string[]) (fltr:string) =
Array.zip first second
|> Array.filter (fun (_, s) ->
Seq.forall (fun c -> s.Contains (string c)) fltr)
|> Array.map fst
|> Array.reduce (*)
let third =
[for i in [0..fltr.Length - 1] do
yield (filterProduct first second fltr.[i])]
|> List.toArray
printfn "Third: %A" third
// Expected Result: Third: [| 42.0; 110.0; 231.0 |]
// Actual Result Third: [| 42.0; 110.0; 231.0 |]
I am trying to apply a function to two arrays of different lengths but the result is not matching my expectations. I need to reuse elements of the second array (similar to R) to complete the expression:
module SOQN =
open System
let first = [|2; 3; 5; 7; 11|]
let second = [|13; 17; 19|]
let result =
[for i in [0..first.Length-1] do
for j in [0..second.Length-1] do
yield (first.[i] * second.[j])]
printfn "Result: %A" result
// Actual Result: [|26; 34; 38; 39; 51; 57; 65; 85; 95; 91; 119; 133; 143; 187; 209|]
// Expected Result: [|26; 51; 95; 91; 187|]
What am I missing?
I guess you looking for something like this
let result =
Array.mapi
(fun i v -> second.[i % second.Length] * v) first
Here is another way of doing it:
let first = [|2; 3; 5; 7; 11|]
let second = [|13; 17; 19|]
let map2Cycle (x: 'T []) (y: 'T []) (f: 'T -> 'T -> 'S) =
let lenx = Array.length x
let leny = Array.length y
let xInf = Seq.initInfinite (fun _ -> x) |> Seq.concat
let yInf = Seq.initInfinite (fun _ -> y) |> Seq.concat
Seq.map2 f xInf yInf
|> Seq.take (max lenx leny)
|> Array.ofSeq
map2Cycle first second (*)
// val it : int [] = [|26; 51; 95; 91; 187|]
And here is a slightly different one:
let map2Cycle' (x: 'T []) (y: 'T []) (f: 'T -> 'T -> 'S) =
let lenx = Array.length x
let leny = Array.length y
let (x', y') =
if lenx >= leny then x |> Seq.ofArray, Seq.initInfinite (fun _ -> y) |> Seq.concat
else Seq.initInfinite (fun _ -> x) |> Seq.concat, y |> Seq.ofArray
Seq.map2 f x' y'
|> Seq.take (max lenx leny)
|> Array.ofSeq
map2Cycle' first second (*)
// val it : int [] = [|26; 51; 95; 91; 187|]
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.
`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
I'm trying to write a function to return a dynamically typed array. Here is an example of one of the ways I've tried:
let rng = System.Random()
type ConvertType =
| AsInts
| AsFloat32s
| AsFloats
| AsInt64s
type InputType =
| Ints of int[]
| Float32s of float32[]
| Floats of float[]
| Int64s of int64[]
let genData : int -> int -> ConvertType -> InputType * int[] =
fun (sCount:int) (rCount:int) (ct:ConvertType) ->
let source =
match ct with
| AsInts -> Array.init sCount (fun _ -> rng.Next()) |> Array.map (fun e -> int e) |> Ints
| AsFloat32s -> Array.init sCount (fun _ -> rng.Next()) |> Array.map (fun e -> float32 e) |> Float32s
| AsFloats -> Array.init sCount (fun _ -> rng.Next()) |> Array.map (fun e -> float e) |> Floats
| AsInt64s -> Array.init sCount (fun _ -> rng.Next()) |> Array.map (fun e -> int64 e) |> Int64s
let indices = Array.init rCount (fun _ -> rng.Next sCount) |> Array.sort
source, indices
The problem I have is that on down when I use the function, I need the array to be the primitive type e.g. float32[] and not "InputType."
I have also tried doing it via an interface created by an inline function and using generics. I couldn't get that to work how I wanted either but I could have just been doing it wrong.
Edit:
Thanks for the great reply(s), I'll have to try that out today. I'm adding the edit because I solved my problem, although I didn't solve it how I wanted (i.e. like the answer). So an FYI for those who may look at this, I did the following:
let counts = [100; 1000; 10000]
let itCounts = [ 1000; 500; 200]
let helperFunct =
fun (count:int) (numIt:int) (genData : int -> int -> ('T[] * int[] )) ->
let c2 = int( count / 2 )
let source, indices = genData count c2
....
[<Test>]
let ``int test case`` () =
let genData sCount rCount =
let source = Array.init sCount (fun _ -> rng.Next())
let indices = Array.init rCount (fun _ -> rng.Next sCount) |> Array.sort
source, indices
(counts, itCounts) ||> List.Iter2 (fun s i -> helperFunct s i genData)
.....
Then each proceeding test case would be something like:
[<Test>]
let ``float test case`` () =
let genData sCount rCount =
let source = Array.init sCount (fun _ -> rng.Next()) |> Array.map (fun e -> float e)
let indices = Array.init rCount (fun _ -> rng.Next sCount) |> Array.sort
source, indices
.....
But, the whole reason I asked the question was that I was trying to avoid rewriting that genData function for every test case. In my real code, this temporary solution kept me from having to break up some stuff in the "helperFunct."
I think that your current design is actually quite good. By listing the supported types explicitly, you can be sure that people will not try to call the function to generate data of type that does not make sense (say byte).
You can write a generic function using System.Convert (which lets you convert value to an arbitrary type, but may fail if this does not make sense). It is also (very likely) going to be less efficient, but I have not measured that:
let genDataGeneric<'T> sCount rCount : 'T[] * int[] =
let genValue() = System.Convert.ChangeType(rng.Next(), typeof<'T>) |> unbox<'T>
let source = Array.init sCount (fun _ -> genValue())
let indices = Array.init rCount (fun _ -> rng.Next sCount) |> Array.sort
source, indices
You can then write
genDataGeneric<float> 10 10
but people can also write genDataGeneric<bool> and the code will either crash or produce nonsense, so that's why I think that your original approach had its benefits too.
Alternatively, you could parameterize the function to take a converter that turns int (which is what you get from rng.Next) to the type you want:
let inline genDataGeneric convertor sCount rCount : 'T[] * int[] =
let genValue() = rng.Next() |> convertor
let source = Array.init sCount (fun _ -> genValue())
let indices = Array.init rCount (fun _ -> rng.Next sCount) |> Array.sort
source, indices
Then you can write just getDataGeneric float 10 10 which is still quite elegant and it will be efficient too (I added inline because I think it can help here)
EDIT: Based on the Leaf's comment, I tried using the overloaded operator trick and it turns out you can also do this (this blog has the best explanation of what the hell is going on in the following weird snippet!):
// Specifies conversions that we want to allow
type Overloads = Overloads with
static member ($) (Overloads, fake:float) = fun (n:int) -> float n
static member ($) (Overloads, fake:int64) = fun (n:int) -> int64 n
let inline genDataGeneric sCount rCount : 'T[] * int[] =
let convert = (Overloads $ Unchecked.defaultof<'T>)
let genValue() = rng.Next() |> convert
let source = Array.init sCount (fun _ -> genValue())
let indices = Array.init rCount (fun _ -> rng.Next sCount) |> Array.sort
source, indices
let (r : float[] * _) = genDataGeneric 10 10 // This compiles & works
let (r : byte[] * _) = genDataGeneric 10 10 // This does not compile
This is interesting, but note that you still have to specify the type somewhere (either by usage later or using a type annotation). If you're using type annotation, then the earlier code is probably simpler and gives less confusing error messages. But the trick used here is certainly interesting.