将递归限制为浮点列表的前三个元素

时间:2017-09-14 03:01:55

标签: recursion functional-programming ocaml reason

我是函数式编程的新手(ReasonML / OCaml)。

我有一张浮动列表。我想获得列表中的前三个非零项目而不是更多。项目可以是正数,负数和零。

在提取前三个非零浮点数之前,如何限制递归?

我在想做类似的事情:

switch (list) {
  | [first, second, third, ...rest] => (first +. second +. third) /. 3.0
  | _ => 0.0
};

但我怎样才能保证firstsecondthird是非零浮点数?如果是,则递归丢弃它们,直到找到三个非零浮点数 - 或者返回0.0

2 个答案:

答案 0 :(得分:1)

使用递归更好的方法是使它更通用:不是找到第一个非零的3,让我们找到.第一个非零。

下面是一个OCaml实现,我不知道Reason。

n

这是函数的签名:

let rec find_n l n ~f =
  if n = 0 then []
  else match l with
  | [] -> failwith "Cannot find enough items"
  | h::t ->
      if f h then
        h :: (find_n t (n-1) ~f)
      else
        find_n (t n ~f)

这里有很多事情,但并不是那么糟糕。这里的逻辑如下:

  

如果我想要列表中的3个项目:

     
      
  • 如果它的头部匹配,那么我需要在尾部找两个项目。
  •   
  • 否则,我仍然需要在尾巴中寻找3个项目。
  •   

其他一切只是额外的逻辑:

  
      
  • 如果我要找0件,我就完蛋了。
  •   
  • 如果列表为空,我仍然需要查找更多项目,我就失败了。
  •   

关于尾递归的一个词

不幸的是,上面的实现不是tail-recursive,这意味着它将在大型列表上失败。使函数尾递归的常用技术是使用 accumulator (下面代码中的val find_n : 'a list -> int -> f:('a -> bool) -> 'a list = <fun> )来存储中间结果。

然后,我们将这个额外的逻辑封装在本地辅助函数(通常称为accloop)中,以便累加器不会显示在函数的签名中。

aux

答案 1 :(得分:0)

知道了!

List.filer可用于过滤掉等于零的元素。

let filtered = List.filter (fun item => item != 0.0) list;
switch (filtered) {
  | [first, second, third, ...rest] => (first +. second +. third) /. 3.0
  | _ => 0.0
};