在 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] *)
我想弄清楚如何在 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] *)