在OCAML中使用FOLD的列表函数中的3个元素的分组说明

时间:2018-02-09 20:49:38

标签: recursion ocaml fold

我有一段代码执行以下操作:n个元素列表中的3个元素组。主要功能称为group_by_3。例如,执行group_by_3 [1;2;3;4;5;6;7]会给我([1;2;3],[4;5;6],[7])

let group_by_3 lst =
  let accum = ( [], [], 0 )
  in
  let f (all_groups, current_group, size) x =
    if size = 3
    then ( (List.rev current_group) :: all_groups, 
           [x], 1 )
    else ( all_groups, x::current_group, size+1)
  in
  let (groups, last, _) = List.fold_left f accum lst
  in List.rev ( List.rev last :: groups)

我真的不明白为什么会这样(它在课堂上提供)。

  • all_groups,current_group,size?
  • 是什么?
  • 这是做什么的?

    if size = 3
    then ( (List.rev current_group) :: all_groups, 
           [x], 1 )
    else ( all_groups, x::current_group, size+1)
    

谢谢!

2 个答案:

答案 0 :(得分:-1)

所有组都是最终答案,当前是解析输入时填充的三个元素的组,而大小是当前我想要的实际元素数。

你知道fold_left的行为吗?

答案 1 :(得分:-1)

  

什么是all_groupscurrent_groupsize

这些是通过访问输入序列中的每个项目来生成分组所需的三个 state 。这些单独的状态组合在一个3元组中,形成折叠的单一状态。最终,我们只关心all_groups,而另外两个只是构建它的必要的中间状态。

  • all_groups:这是一个列表值,可以吸收已完成的分组。每当我们看到足够的新元素来满足组大小时,我们就会创建一个新组并将其添加到此列表中。
  • current_group:这也是一个列表值,但更多的是用于构建分组的临时缓冲区,直到达到size。当它足够大时,会被添加到all_groups并重置为包含当前项[x]的新组/列表。
  • size这只是一个跟踪current_group中有多少项目的计数器。
  

这是做什么的?

if size = 3只是决定我们是否要继续积累元素,或者我们是否已经足够进行分组。

then ( (List.rev current_group) :: all_groups, [x], 1 )正在构建/返回新的累加器值,该值是all_groupscurrent_groupsize的3元组。由于列表的增长方式,在{em> else 分支中,List.rev调用是必要的。将项添加到列表的前面是最快的,但这是输入序列的 reverse ,因此我们将它们反转。 x是当前项目,它将是新增长组中的第一个项目。 1当然是新组的大小。

else ( all_groups, x::current_group, size+1)将当前项x弹出到current_group列表的正面并递增size计数器。

在该部分下面是处理任何不适合三个分组的落后者项目的逻辑。