因此,我目前正在尝试找出如何编写一个函数,该函数采用2个相等长度的列表,并通过折叠将两个列表的相同位置相乘,并将结果作为新的List返回。
eg) let prodList [1; 2; 3] [4; 5; 6] ;;
==> (through folding) ==> [1*4; 2*5; 3*6]
==> result = [4; 10; 18]
我觉得我需要使用List.combine,因为它将把需要相乘的值放入元组中。之后,我无法弄清楚如何以允许我乘以值的方式拆分元组。这是我到目前为止的内容:
let prodLists l1 l2 =
let f a x = (List.hd(x)) :: a in
let base = [] in
let args = List.rev (List.combine l1 l2) in
List.fold_left f base args
我在正确的轨道上吗?
答案 0 :(得分:0)
您可以使用fold_left2
来折叠两个相同长度的列表。该文档可以为您提供更多详细信息(https://caml.inria.fr/pub/docs/manual-ocaml/libref/List.html):
val fold_left2 : ('a -> 'b -> 'c -> 'a) -> 'a -> 'b list -> 'c list -> 'a
List.fold_left2 f a [b1; ...; bn] [c1; ...; cn]
是f (... (f (f a b1 c1) b2 c2) ...) bn cn
。如果确定两个列表的长度不同,请提高Invalid_argument
。
另一种方法是按照您的建议折叠合并的输出,我建议您在看下面的解决方案之前自己尝试。
解决方案:
let prod_lists l s =
List.rev (List.fold_left2 (fun acc a b -> (a * b) :: acc) [] l s);;
let prod_lists' l s =
List.fold_left (fun acc (a, b) -> (a * b) :: acc) [] (List.rev (List.combine l s));;
答案 1 :(得分:0)
首先让我注意到,使用fold来实现此操作似乎有些强制,因为您必须同时遍历两个列表。但是,折叠合并了单个列表的元素。尽管如此,这是一个实现。
let e [] = []
let f x hxs (y::ys) = (x*y) :: hxs ys
let prodList xs ys = List.fold_right f xs e ys
看起来有点复杂,所以让我解释一下。
对折的通用属性
首先,您应该了解fold_right
的以下属性。
h xs = fold_right f xs e
当且仅当
h [] = e
h (x::xs) = f x (h xs)
这意味着,如果我们以下面的递归形式编写列表的乘法,则可以使用e
和f
来使用fold来编写它。请注意,尽管我们正在操作两个列表,所以h
接受两个参数。
基本案例-空列表
将两个空列表相乘会返回一个空列表。
h [] [] = []
如何在上面的表格中写这个?只是抽象第二个参数。
h [] = fun [] -> []
所以
e = fun [] -> []`
或等效地
e [] = []
递归案例-非空列表
h (x::xs) (y::ys) = x*y :: h xs ys
或者,仅使用一个参数,
h (x::xs) = fun -> (y::ys) -> x*y :: h xs ys
现在,我们需要以h (x::xs) = f x (h xs)
的形式重写此表达式。它可能看起来很复杂,但是我们只需要对x
和h xs
进行抽象。
h (x::xs) = (fun x hxs -> fun (y::ys) -> x*y :: hxs ys) x (h xs)
所以我们有f
由
f = fun x hxs -> fun (y::ys) -> x*y :: hxs ys
或等效地
f x hxs (y::ys) = x*y :: hxs ys
解决方案
确定了e
和f
之后,我们根据上述属性的第一个方程式将其插入折叠。我们得到
h xs = List.fold_right f xs e
或等效地
h xs ys = List.fold_right f xs e ys
了解实施情况
请注意,List.fold_right f xs e
的类型为int list -> int list
,因此折线在列表上构建了一个函数,给定某些ys
会将其与给定参数xs
相乘。
对于空xs
,您将期望空ys
并返回空结果,因此
e [] = fun [] -> []
对于递归情况,f
中的函数fold_right
必须实现x::xs
的解决方案。因此,xs
采用f
类型的x
和int
类型的函数hxs
来实现尾部的乘法,并且必须实现{ {1}}。
int list -> int list
因此,x::xs
构造了一个将f x hxs = fun (y::ys) -> x*y :: hxs ys
与f
相乘的函数,然后将其应用于x
并将{{1}到列表。
答案 2 :(得分:0)
您大多有正确的想法;您需要先combine
(其他语言zip
)两个列表,然后在每个元组上map
:
let prod_lists l1 l2 =
List.combine l1 l2
|> List.map (fun (a, b) -> a * b)
关键是您可以使用(a, b)
在该元组上进行模式匹配。
如果您不想使用fold
,也可以rev
在合并列表上,然后map
,结果。