slowpoke
slowpoke

Reputation: 123

Elementwise addition of lists in F#

I'm trying to figure out how to do elementwise multiplication of two lists in F#. Example: [1;2;3]+[1;2;3;4]=[2;4;6;4]. I'm quite a newbie and still struggle with the syntax of the code. My try is as follows:

let plus list_1 list_2 = function
    | list_1 list_2 -> [| for xi in list_1 yield
                          list_1[i]+list_2[i]
                          |];;

It just give me an error, but can't figure out how to change it so it becomes right.

As a side note, if somebody know a beginner place to learn about lists in F#, a point in the right direction, is appreciated :)

Upvotes: 0

Views: 132

Answers (3)

David Raab
David Raab

Reputation: 4498

Here are two different solutions. Both combine the elements, that can be combined, and concatenate the result, onto the end.

It's up to you, to understand, how they work.

(* Avoiding SO syntax highlighting issues *)
let add x y = x + y
let mul x y = x * y


let dol f xs ys =
    let minElements = min (List.length xs) (List.length ys)
    List.append
        (List.map2 f (List.take minElements xs) (List.take minElements ys))        
        (List.skip minElements (if List.length xs = minElements then ys else xs))
 
dol add [1;2;3] [2;3;4;5;6] (* [3; 5; 7; 5; 6]  *)
dol mul [1;2;3] [2;3;4;5;6] (* [2; 6; 12; 5; 6] *)


let rec mol f xs ys =
    match xs,ys with
    | [],[]       -> []
    | [],ys       -> ys
    | xs,[]       -> xs
    | x::xs,y::ys -> (f x y) :: (mol f xs ys)

mol add [1;2;3] [2;3;4;5;6] (* [3; 5; 7; 5; 6]  *)
mol mul [1;2;3] [2;3;4;5;6] (* [2; 6; 12; 5; 6] *)

Upvotes: 0

anton.burger
anton.burger

Reputation: 5706

In a similar vein to Tomas's answer, this makes both lists the "same" (infinite) length (using the lazy Seq instead of eager List), then trims the result to just the maximum length of the two lists:

let l1 = [1;2;3]
let l2 = [3;2;1;4]

let zeroes = Seq.initInfinite (fun _ -> 0)

let result =
    Seq.map2 (+) (Seq.append l1 zeroes) (Seq.append l2 zeroes)
    |> Seq.take (max (List.length l1) (List.length l2))
    |> Seq.toList

Upvotes: 1

Tomas Petricek
Tomas Petricek

Reputation: 243096

If you had two lists of the same size, then the easiest solution would be to use the List.map2 function. This takes two lists and it applies a specified function pairwise - so if you pass it (+) as a function, it does exactly what you want:

let l1 = [1;2;3]
let l2 = [3;2;1]

List.map2 (+) l1 l2

If your lists are of different size, then this is going to crash. I do not think there is any simple built-in solution, but you could define a function pad to pad a list with zeros and then make sure both lists are of the same size:

let pad n l = 
  List.append l 
    (List.init (n-List.length l) (fun _ -> 0))

let l1 = [1;2;3]
let l2 = [3;2;1;4]
let l = max (List.length l1) (List.length l2)

List.map2 (+) (pad l l1) (pad l l2)

Upvotes: 1

Related Questions