Krzysztof Piszko
Krzysztof Piszko

Reputation: 1445

OCaml - How do I return list of lists from a list?

I have a following problem. From a list, I must separate mod 3 = 0 element, mod 3 = 1 element and mod 3 = 2 element to 3 different lists and return list of these 3 lists. My question is pretty obvious - how do I do that? Is there some kind of simple rule to this I'm missing?

What I have so far is not much but there you go:

let separate xs =
    let rec help xs i =
    match xs i with
    | [] _ -> []
    | hd a -> if a mod 3 = 0 //HOW DO I RETURN
                        else if a mod 3 = 1
                        else

UPDATED: Finished code:

let separate xs = 
let rec help (list, i, xs1, xs2, xs3) = 
    match list with
    | [] -> [xs1;xs2;xs3]
    | head :: tail -> (if i mod 3 = 0 then help (tail, i+1, head::xs1, xs2, xs3)
                                        else if i mod 3 = 1 then help (tail, i+1, xs1, head::xs2, xs3)
                                        else help (tail, i+1, xs1, xs2, head::xs3))
in help (xs, 0, [], [], []);;

Upvotes: 1

Views: 955

Answers (2)

ivg
ivg

Reputation: 35210

A usual way is to use List.fold* function, that generalizes an idea of list iteration. But, in your case, it may not be appropriate (depending on what your teachers are asking).

You can iterate over your list maintaining some notion of state (indeed, you need three extra "variables" for three different lists). Here is a pattern for iterating over lists

let my_function lst = 
  let rec loop acc lst = match lst with
    | [] -> <do_some_post_iteration_work> acc
    | head :: rest -> 
       let result = <do_something_with_nth_element> head in
       let accum  = <add_result_to_accumulator> result acc in
       loop accum rest in
  let accum = <initialize_accumulator> in
  loop accum lst

I used long names so that you can understand the meaning without extra comments, although you're welcome to ask. Also, keep in mind, that your state (aka accumulator), can be also a value of any type. Using a triple would be a not a bad idea in your case.

Upvotes: 1

Marth
Marth

Reputation: 24812

You'll need to accumulate the partial results in lists, and then return those lists :

let split_by_mod_3 l =
  let rec aux l mod0 mod1 mod2 = match l with
    | [] -> [mod0; mod1; mod2]
    | hd::tail when hd mod 3 == 0 -> aux tail (hd::mod0) mod1 mod2
    | hd::tail when hd mod 3 == 1 -> aux tail mod0 (hd::mod1) mod2
    | hd::tail when hd mod 3 == 2 -> aux tail mod0 mod1 (hd::mod2)
  in
  aux l [] [] [];;

Upvotes: 2

Related Questions