所以考虑获取一个
[1; 2; 3; 4; 5; 6; 7; 8; 9]
的列表并将其重塑为[[1; 2; 3]; [4; 5; 6]; [7; 8; 9]]
。你会如何在 OCaml 中做到这一点?我想要一个简单的函数或标准库中的东西。
事实证明,考虑到列表的长度可以被 3 整除,只需 3 行代码就可以轻松完成。
let rec re_shape = function
| x :: xs :: xz :: xt -> [x; xs; xz] :: re_shape xt
| _ -> []
这是如何工作的,对于每次迭代,它都包含一个 3 列表到函数的其余部分,直到它到达结尾。添加最后一行是为了安全。
正如您所展示的解决此问题的努力,为了您的考虑,请参阅下面的a策略以将其概括为允许任何长度。
partition
函数将允许我们从列表中获取前 n
元素和其余元素,如果列表中没有 Invalid_argument
元素,则提高 n
。
chunks
函数递归地将此应用于余数以构建列表列表。
let partition n lst =
let rec partition' n (first, rest) =
match n, rest with
| 0, _ -> (List.rev first, rest)
| _, [] -> invalid_arg "List not long enough"
| _, x::xs -> partition' (n-1) (x :: first, xs)
in
partition' n ([], lst)
let rec chunks n lst =
match partition n lst with
| first, [] -> [first]
| first, rest -> first :: chunks n rest
| exception (Invalid_argument _) ->
invalid_arg @@ Format.sprintf "List length not evenly divisible by %d" n
第二个函数是 not 尾递归的,尽管这可以很容易地在 OCaml 4.14 和更高版本中解决:
let[@tail_mod_cons] rec chunks n lst =
...