I am trying to subtract an n-1 element as part of a calculation using a constant and two arrays as follows:
module SOQN =
open System
let firstArray = [|0.02;0.03;0.05;0.07;0.11|]
let secondArray = [|0.30;0.50;0.70;1.10;1.30|]
let constant = 0.37
let minusOneElement = 0.00
let result = Array.map2 (fun x y -> (x - (constant * (y - minusOneElement)))) firstArray secondArray
printfn "Result: %A" result
(*
Expected Result: [|-0.091;-0.044;-0.024;0;0|]
Actual Result: [|-0.091;-0.155;-0.209;-0.337;-0.371|]
*)
As you can see, the first output value is correct but the rest are not given that I do not know how to construct "minusOneElement", which should be successive elements of "secondArray" - namely, 0.30 0.50 0.70 and 1.10. There is an additional restriction that the current element of "secondArray" be less than one; otherwise, the corresponding result value is set equal to zero.
If I interpret your requirements correctly, you wish to take the second array and generate pairs (current element, previous element), where the previous element is set to 0.0 for the first current element.
You can use Seq.windowed to generate the pairs (after prepending a singleton array of 0.0 for the first previous element):
let fst = [|0.02;0.03;0.05;0.07;0.11|]
let snd = [|0.30;0.50;0.70;1.10;1.30|]
let snd' = Seq.windowed 2 (Array.append [|0.0|] snd) |> Seq.toArray
let constant = 0.37
Revising your map operation:
let result = Array.map2 (fun x (y: float []) -> (if y.[1] < 1.00 then (x - (constant * (y.[1] - y.[0]))) else 0.00)) fst snd'
Which yields your expected result (note the snd' pairs for reference):
val snd' : float [] [] =
[|[|0.0; 0.3|]; [|0.3; 0.5|]; [|0.5; 0.7|]; [|0.7; 1.1|]; [|1.1; 1.3|]|]
val result : float [] = [|-0.091; -0.044; -0.024; 0.0; 0.0|]
The following snippet appears to work:
module SOANS =
open System
let firstArray = [|0.02;0.03;0.05;0.07;0.11|]
let secondArray = [|0.30;0.50;0.70;1.10;1.30|]
let lenSecondArray = secondArray.Length
let thirdArray = Array.permute (fun index -> (index + (1)) % lenSecondArray) secondArray
thirdArray.[0] <- 0.00
let constant = 0.37
let result = Array.map3 (fun x y z -> (if y < 1.00 then (x - (constant * (y - z))) else 0.00)) firstArray secondArray thirdArray
printfn "Result: %A" result
(*
Expected Result: [|-0.091;-0.044;-0.024;0;0|]
Actual Result: [|-0.091;-0.044;-0.024;0;0|]
*)
I would appreciate a more idiomatic solution, if possible.
For each y.[n]
, construct a tuple of it and of its difference to y.[n-1]
. A functional way to this end is a scan
operation, which populates the collection with the intermediate results of a fold
. In contrast to Seq.windowed
(or for that matter, Seq.pairwise
), the length of the resulting collection is not less than the source. It contains one extra element, the initial state is prepended.
let first = [|0.02;0.03;0.05;0.07;0.11|]
let second = [|0.30;0.50;0.70;1.10;1.30|]
let diff2 = Array.scan (fun (prv, _) cur -> cur, cur - prv) (0., 0.) second
(first, diff2.[1..])
||> Array.map2 (fun x (y, dy) ->
if y < 1. then x - 0.37 * dy else 0. )
// val it : float [] = [|-0.091; -0.044; -0.024; 0.0; 0.0|]
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.