John John
John John

Reputation: 377

F# Swap arrays of data and get the correct results

let highs = [| 2; 4; 6 |]
let lows = [| 1; 5; 10 |]

I want to get 2 arrays from the above: if the element in highs is smaller than the corresponding element in lows, then swap them. So, I can get the final 2 arrays:

let trueHighs = [| 2; 5; 10 |]
let trueLows = [| 1; 4; 6 |]

How do I do this?

Upvotes: 3

Views: 252

Answers (3)

Daniel
Daniel

Reputation: 47914

Here is the code you should use:

let n = highs.Length
let trueHighs = Array.init n (fun i -> max highs.[i] lows.[i])
let trueLows = Array.init n (fun i -> min highs.[i] lows.[i])

If performance is uber-critical, you're probably better off with an imperative approach.

let n = highs.Length
let trueHighs = Array.zeroCreate n
let trueLows = Array.zeroCreate n
for i = 0 to n-1 do
  let hi = highs.[i]
  let lo = lows.[i]
  if hi > lo then
    trueHighs.[i] <- hi
    trueLows.[i] <- lo
  else
    trueHighs.[i] <- lo
    trueLows.[i] <- hi

Upvotes: 3

pad
pad

Reputation: 41290

Similar with JaredPar's answer but simpler:

let trueHighs, trueLows =        
    Array.zip highs lows
    |> Array.map (fun (x, y) -> if x >= y then (x, y) else (y, x))
    |> Array.unzip

Another more concise version:

let trueHighs, trueLows =        
    (highs, lows)
    ||> Array.map2 (fun x y -> if x >= y then (x, y) else (y, x))    
    |> Array.unzip

Upvotes: 5

JaredPar
JaredPar

Reputation: 755141

Try the following

let trueHighs, trueLows = 
  let zipped = 
    highs
    |> Seq.ofArray
    |> Seq.zip (lows |> Seq.ofArray)
    |> Seq.map (fun (x, y) -> min x y, max x y)
  let lows = zipped |> Seq.map fst |> Array.ofSeq
  let highs = zipped |> Seq.map snd |> Array.ofSeq
  highs, lows

Upvotes: 0

Related Questions