So, let us say we have some list like as follows: [1; 2; 3; 4; 5; 6]
, and let us say that I want to fold on 2 elements per call of the function.
So, I would apply the function on (1, 2)
, (3, 4)
, and (5, 6)
in order.
Here was my attempt at a function to do so:
let fold_left_multiple (func: 'a -> 'b list -> 'a) (base: 'a) (lst: 'b list) (items_per_fold: int): 'a * 'b list =
let (acc, remainder, _) = List.fold_left (fun (acc, cur_fold_acc, cur_num) el ->
if cur_num mod items_per_fold = 0 then (func acc (List.rev (el::cur_fold_acc)), [], 1)
else (acc, el::cur_fold_acc, cur_num + 1)
) (base, [], 1) lst in (acc, remainder)
This somewhat works; however, the problem with this is that it is not easy to use these elements in a function.
My preferred implementation would somehow use a tuple or array to make element access easier.
Here is an example of input/output that would be better expected (using utop
syntax). In this case, I am summing up each pair of elements.
# fold_left_multiple (fun lst (e1, e2, e3) -> (e1 + e2 + e3)::lst) [] [1; 2; 3; 4; 5; 6; 7; 8] 3;;
- : int list * int list = ([15; 6], [7; 8])
Here, the remaining elements if the list's length is not evenly divisible by n
are put into the second element of the tuple.
(I would not mind if this remainder is reversed in a solution.)