So consider getting a list of [1; 2; 3; 4; 5; 6; 7; 8; 9]
and reshape it into [[1; 2; 3]; [4; 5; 6]; [7; 8; 9]]
. How would you do that in OCaml? I want a simple function or something from the standard library.
CodePudding user response:
Turns out, it can be easily done with 3 lines of code, considering that the length of the list is divisible by 3.
let rec re_shape = function
| x :: xs :: xz :: xt -> [x; xs; xz] :: re_shape xt
| _ -> []
How this works is that for each iteration it cons a list of 3 to the rest of the function, till it reaches the end. The last line is added for safety.
CodePudding user response:
As you have shown an effort to solve this, for your consideration, see a strategy below for generalizing this to allow for any length.
The partition function will allow us to get the first
nelements from the list and the remainder, raising
Invalid_argumentif there aren't
n` elements in the list.
The chunks
function applies this recursively to the remainder to build a list of lists.
let partition n lst =
let rec partition' n (first, rest) =
match n, rest with
| 0, _ -> (List.rev first, rest)
| _, [] -> raise (Invalid_argument "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 _) ->
raise (Invalid_argument (Format.sprintf "List length not evenly divisible by %d" n))
This second function is not tail-recursive, though that can readily be addressed in OCaml 4.14 and later with:
let[@tail_mod_cons] rec chunks n lst =
...