【问题标题】:Average calculating of consecutive list elements in OCamlOCaml中连续列表元素的平均计算
【发布时间】:2016-10-22 23:33:36
【问题描述】:
我正在尝试在 OCaml 中编写一个函数来计算列表中连续元素的平均值。例如[1; 2; 3; 4] 它应该输出[1; 2; 3]。它应该采用(1 + 2) / 2 并给出1 然后采用(2 + 3) / 2 并给出2 等等。
然而,我写的代码只返回[1; 2]:
let rec average2 xs = match xs with
|[] -> []
|x :: [] -> [x]
|x :: x' :: xs -> if xs = [] then [(x + x') / 2] else [(x + x') / 2] @ (average2 xs)
你能告诉我如何解决这个问题吗?谢谢。
【问题讨论】:
标签:
recursion
ocaml
average
【解决方案1】:
当您在比赛中使用x :: y :: l 时,您实际上是在永久删除列表中的元素。
因此,如果您想对成对的元素进行操作,则需要放回其中一个。
例子:
你有一个[1;2;3;4]的列表
你想对1和2进行操作,在你的比赛中它会解释为:
1 :: 2 :: [3;4]
如果不添加元素继续,下一条语句将是:
3 :: 4 :: []
这不是你想要的。
要纠正这个问题,在你的递归调用中你需要做(average2 (x'::xs) 而不仅仅是(average2 xs) 因为xs 是取出元素后列表的其余部分。
【解决方案2】:
OCaml 允许使用 p as v (alias patterns) 将模式 p 绑定到变量 v:
let rec average2 = function
| x :: (y :: _ as tail) -> (x + y) / 2 :: (average2 tail)
| _ -> []
在上面,y :: _ as tail 将名为tail 的列表解构为一个以y 为首的非空列表,并具有任意尾部_,我们不关心它的值。
请注意,我还简化了您的函数,这样您就不会检查 _ 是否为空:递归在这里为您处理。
此外,当列表中有零个或一个元素时,您应该返回一个空列表。
# average2 [ 10; 20; 30; 40];;
- : int list = [15; 25; 35]