在 F# 中按元素添加列表

Elementwise addition of lists in F#

我想弄清楚如何在 F# 中对两个列表进行元素乘法。示例:[1;2;3]+[1;2;3;4]=[2;4;6;4]。我是一个新手,仍然在为代码的语法而苦苦挣扎。我的尝试如下:

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

它只是给我一个错误,但无法弄清楚如何更改它以使其正确。

附带说明一下,如果有人知道初学者可以在 F# 中学习列表,请指出正确的方向:)

如果您有两个相同大小的列表,那么最简单的解决方案是使用 List.map2 函数。这需要两个列表,并且它成对地应用指定的函数 - 所以如果你将它 (+) 作为函数传递,它会完全按照你的要求执行:

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

List.map2 (+) l1 l2

如果您的列表大小不同,那么这将会崩溃。我认为没有任何简单的内置解决方案,但您可以定义一个函数 pad 来用零填充列表,然后确保两个列表的大小相同:

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)

与 Tomas 的回答类似,这使得两个列表的长度“相同”(无限)(使用惰性 Seq 而不是急切的 List),然后将结果修剪为两个列表的最大长度:

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

这里有两种不同的解决方案。两者都结合了可以结合的元素,并将结果连接到最后。

这取决于你,了解它们是如何工作的。

(* 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] *)