user4165421
user4165421

Reputation: 131

OCaml - splitting list into two separate, greater or lesser than given number

I have a problem with writing a function which result is as shown below:

split([7;1;4;3;6;8;2], 4) = ([1;3;2;4], [7;6;8])

my current code i managed to write:

let split(list, number)=
  let split1(list, number, lesser, greater)=
    if list = [] then lesser::greater
    else if List.hd list <= element then (List.hd list)::(lesser)
    else (List.hd list)::(greater)
  in 
  (List.tl lista, element, [], []);;

Thanks in advance for your help.

Upvotes: 1

Views: 5737

Answers (2)

user3125280
user3125280

Reputation: 2829

For the future, it helps to be more specific when asking a question on SO. What exactly is your problem? SO users will be skeptical of someone who wants others to help them, but won't help themselves.

Your code has nearly the correct structure, but there are a few errors in there that seem to be getting in your way.

Firstly lesser::greater is wrong, since the left hand side of a cons operator must be a list itself, but what you really want is a list where both of these are elements. So instead try [lesser;greater].

Secondly, if you think through your code, you will notice that it suddenly stops. You checked the first element, but you didn't look at the rest of the list. Since you want to keep splitting the list, you need your code to keep executing till the end of the list. To achieve this, we use recursion. Recursion mean that your function split1 will call itself again. It can be very confusing the first time you see it - each time split1 runs it will take the first element off, and then split the remainder of the list.

What does (List.hd list)::(lesser) actually mean? The lesser here really means all of the lesser elements in the rest of the list. You need to keep taking an element out of the list and putting it in either lesser or greater.

Finally avoid using List.hd excessively - it is neater to find the head and tail using pattern matching.

Here's a working version of the code:

let split(list, number)=
  let rec split1(list, number, lesser, greater)=
    match list with
    | [] -> [List.rev lesser;List.rev greater]
    | head::tail ->
      match (head <= number) with
        true  -> split1(tail,number,head::lesser,greater)
      | false -> split1(tail,number,lesser,head::greater)
  in split1(list, number, [], []);;

split([1;2;3;4;5],3);;

The split1 function takes the elements off one at a time, and adds them to the lists.

Upvotes: 1

&#199;ağdaş Bozman
&#199;ağdaş Bozman

Reputation: 2540

Maybe my comments on the following code snippet would help:

let split list num = 
  let rec loop lesser greater list =
    match list with
    | [] -> (lesser, greater)
    (* when your initial list is empty, you have to return the accumulators *)
    | x :: xs ->      
      if x <= num then 
          (* x is lesser than num, so add x in the lesser list and
             call loop on the tail of the list (xs)  *) 
      else 
          (* x is greater than num, so add x in the greater list and
             call loop on the tail of the list (xs)  *)  
  in
  (* here you make the first call to loop  by initializing 
     your accumulators with empty list*)
  loop [] [] list 

Upvotes: 1

Related Questions