Home > Software design >  How to reshape a list in OCaml
How to reshape a list in OCaml

Time:12-13

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, raisingInvalid_argumentif there aren'tn` 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 =
  ...
  • Related