如何解决ocaml 列表元素的总和 附加说明
我是 ocaml 的新手,我坚持这两个练习
1- 第一个我必须对列表中的元素求和,每个元素都乘以自己的位置
对于列表 l [4; 7; 3]
结果应该是 4x1 + 7x2 + 3x3 = 25
我试过这个代码
let rec sum l n =
if l = [] then 0
else (List.hd l) * (List.length l/List.length l) + (sum(List.tl l (n-1 ) * (List.length l - 1)));;
但没有成功
任何帮助将不胜感激
第二个练习
就是以这种方式计算列表元素的总和
`the result would be 7+1 = 8 they are of the same parity`
`8-3 = 5 there are not of te same parity`
``
`5-2 = 3 there are not of te same parity`
`3 + 3 =6 they are the same parity the last result
非常感谢任何帮助
谢谢大家
解决方法
这两个练习非常相似,都要求您在保持状态的同时遍历列表中的所有元素。
首先,最终结果必须作为正在浏览的索引进行维护。我们可以使用一对两个整数作为状态,其中第一个是遍历索引,第二个是累积结果,例如 (1,0)
。
let sum list =
(* We define an internal function hiding the details *)
let rec aux_sum (i,result) list =
match list with
| [] ->
(* If we reach the end of the
list,we can returns the result. *)
result
| x :: xs ->
(* Otherwise,we can accumulate the result and
processing the tail (`xs`) of the list. *)
aux_sum (i + 1,result + (x * i)) xs
in aux_sum (1,0) list
第二种大致相同,只是要维护的状态要简单得多。确实,不需要维护索引,只维护当前状态即可。
let other_sum list =
(* Like previously,we define an internal function
hiding the details *)
let rec aux_sum result list =
match list with
| [] ->
(* The iteration is done,we can returns
the result. *)
result
| x :: xs ->
let new_result =
if (x mod 2) = (result mod 2)
then (* Same parity *)
result + x
else (* Not the same parity *)
result - y
in (* We can loop *)
aux_sum new_result xs
in
(* Now,we have to get the first element of the list
in order to deal with *)
match list with
| [] -> 0
| x :: xs -> aux_sum x xs
这两个函数的结构大体相似,主要区别在于:
- 维护的状态类型
- 应用于每次迭代的逻辑
- 初始值的定义。
附加说明
在函数式编程中,通过累加结果递归遍历结构是一种相当普遍的做法,因此为了减少样板,通常使用组合器。这种“减少”列表的方式称为“折叠”。在标准的 OCaml 库中,有一个 fold_left
函数 (https://ocaml.org/api/List.html#VALfold_left) 可以完成我们刚刚完成的工作。例如,我们可以如下重写我们的第一个函数:
let sum list =
let (_last_index,result) =
List.fold_left
(fun (i,result) x -> (i + 1,result + (i * x)))
(1,0)
list
in result
由于我们已经概括了我们的迭代/累加,最后我们有我们的 (index,result)
对,但我们只想要结果,所以我们只使用模式匹配提取结果。
尽管这个函数要短得多,但它和我们定义的第一个函数做的完全一样,如果仔细观察,你会发现相同的成分(初始状态、累积逻辑)。
第二个示例也可以表示为 fold
。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。