我有一个执行以下代码的代码: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)
谢谢!
什么是
all_groups
,current_group
,size
?
这是通过访问输入序列中的每个项目所需的三个状态所需的三个部分。将这些单个状态组合成一个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_groups
,current_group
和size
的3核。List.rev
呼叫是必要的,因为列表的种植方式,在 else 分支中;将项目添加到列表的 front 中最快,但这是输入序列的反向,因此我们将其逆转。x
是当前项目,它将是新成长组中的第一项。1
当然是那个新组的大小。
else ( all_groups, x::current_group, size+1)
将当前项目 x
弹出到current_group
列表的正面并增加size
计数器。
该部分下方是逻辑,它照顾任何不整齐地组成三个分组的straggler项目。