I am new to OCaml, and I am now trying to implement a function that returns a list containing all the elements in even position in the input list. For [1;2;3;5] returns [2;5] and for [1 3] returns [3]; and for ["i";"am";"new";"to";"ocaml"] returns ["am";"to"]. Hope someone can give me some suggestions to solve this problem.
问题:
回答1:
There's nothing particularly OCaml-like in this problem. Most likely your main task is to learn to solve problems recursively.
The way to solve a problem recursively is to break it into two cases:
a. The input is so small the answer is ridiculously obvious.
b. The answer isn't so small, but you already have a function that works for (strictly) smaller inputs.
To solve the problem, you need to decide how to determine whether the input size is ridiculously small (a very short list), and how to use another function that works for smaller lists to solve your problem with a larger list. Then your own function is that other function (when called recursively).
回答2:
Well, you want to descend through your list getting elements two by two and forgetting the first one.
let rec get_even = function
| _ :: y :: tl -> y :: (get_even tl)
Then, you need to make sure of what happens when you get to the end of the list. But there can be two ways to get there, depending on the parity of List.length l
.
So, your final code would look like:
let rec get_even = function
| x :: y :: tl -> y :: (get_even tl)
| [] | _::[] -> []
Note that this function is not tail-recursive, meaning it will put weight on your stack. This is not a problem over lists smaller than your stack, but may be problematic if you're going to handle big data. In that case, you may want to use a data structure more adapted to your problem.
回答3:
Here is one solution:
let rec even_elements l index acc_l = match l with h::t -> if (index mod 2 == 0 ) then even_elements t (index+1) (acc_l@[h]) else even_elements t (index+1) acc_l | [] -> acc_l;;
You would call it like this:
even_elements [1;2;3;4;5;6] 1 []
I am iterating over the list:
match l with h::t
checking if I am at an even index:
if (index mod 2 == 0 )
and if I am I will append it to the accumulator:
even_elements t (index+1) (acc_l@[h])
If I am not I won't:
even_elements t (index+1) acc_l
Also note that for the first argument I pass in t not l. Which is the tail of the list.
At the end of the list I return the accumulator which should have all the even elements:
| [] -> acc_l