matekus
matekus

Reputation: 788

F# - Apply Function To Two Arrays Of Different Lengths

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?

Upvotes: 0

Views: 217

Answers (2)

Soldalma
Soldalma

Reputation: 4758

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|]

Upvotes: 0

FoggyFinder
FoggyFinder

Reputation: 2220

I guess you looking for something like this

let result = 
    Array.mapi
        (fun i v -> second.[i % second.Length] * v) first

Upvotes: 4

Related Questions