如何解决有没有办法乘以对列表中的元素
你好,我正在尝试用 OCaml 编写一个程序,想知道是否有办法从对列表中获取:[(1,2);(2,3);(3;5)] 到一个列出成对相乘的 [2;6;15] 这是我尝试过的,但它给了我例外:失败“hd”
let rec mul l=
let x=(List.hd l) and y=(List.tl l) in
((fst x)*(snd x))::(mul y);;
mul [(3,5); (3,4); (3,3);];;
解决方法
老实说,我认为肯定有更简单的方法。具体来说,您有一个 n
元素的列表,它们是成对的(因此是一个 (int * int) list
类型的列表),并且您想要获得一个相同大小的列表,但这是两个成员相乘的结果对。所以,从 (int * int) list
到 int list
。
由于目标是保持列表的大小,您可以通过说“我想对列表的每个元素应用一个函数”来重新表述该语句。可以手动执行此操作,例如使用模式匹配(这使得可以明确处理空列表):
let rec mult my_list =
match my_list with
| [] -> (* case if my list is empty *)
[] (* The process is done! *)
| (a,b) :: tail -> (* if I have,at least,one element)
(a * b) :: (mult tail)
但通常,将函数应用于列表的每个元素并保留其大小称为“映射”(大致),幸运的是,标准 OCaml 库中有一个函数允许这样做,并且在逻辑上调用它: List.map
,这是它的类型:val map : ('a -> 'b) -> 'a list -> 'b list
可以翻译为:给我一个从 'a
到 'b
的函数,一个 'a
列表和我可以为您制作一份 'b
列表。
在这里,我们希望能够应用来自 (int * int) -> int
的函数,例如:let prod (x,y) = x * y
。因此,让我们尝试根据 mult
重新实现 map
:
let mult my_list =
let prod (x,y) = x * y in
List.map prod my_list
瞧,第一个目的中捕获的模式正是 List.map
背后的想法,对于列表的每个元素,我应用一个函数并保留该函数应用的结果。
本质上你想要的是List.map (uncurry ( * ))
。
# let uncurry f (a,b) = f a b;;
val uncurry : ('a -> 'b -> 'c) -> 'a * 'b -> 'c = <fun>
# List.map (uncurry ( * )) [(3,5); (3,4); (3,3);];;
- : int list = [15; 12; 9]
(uncurry
是一个基本的 FP 函数,但不幸的是它没有在 OCaml 相当稀疏的标准库中定义。但正如你所看到的,定义很简单。)
这是对原始代码修改最少的可行解决方案:
let rec mul l =
match l with
| [] -> [] (* <-- Deal with the base case *)
| _ -> (* Same as before --> *)
let x = (List.hd l) and y = (List.tl l) in
((fst x)*(snd x))::(mul y);;
请注意,我们只需要考虑列表为空时发生的情况,我们通过在列表上进行匹配来实现。递归情况保持不变。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。