iteration to construct a function between two arrays in ocamlre
I have question regarding constructing a function like thi开发者_JS百科s.
Here, I have two lists, both have the same length (say that the length is n
, and the case that I want is a function which fulfil this requirement:
list1.(0) -> list2.(0)
list1.(1) -> list2.(1)
...
list1.(n-1) -> list2.(n-1)
How to do it? Should I do iteration inside a function (and how)? Or appending two functions (and how)? There must be tricky way to answer thing like this.
Sorry, have to answer this by myself. I just find that this is actually quite easy. I can easily create a function f
which is written by nlucaroni much shorther.
let rec f domain range x =
match (List.hd domain) = x with
| true -> (List.hd range)
| false -> f (List.tl domain) (List.tl range) x;;
From my understanding, you have two arrays. One defines the domain of the function, another the range. And you want to write an ocaml function that represents this function. I am assuming here that the function is bijective. The missing part, the meat, is a function to find the index of an element in an array. In the spirit of List.find
, I decided to pass a function to define this comparison.
let find_index p array =
let rec find_index idx =
if idx = (Array.length array) then raise Not_found
else if (p array.(idx)) then idx
else find_index (idx+1)
in
find_index 0
From here it is trivial to create the function, and its inverse,
let f domain range x = range.(find_index (fun y -> 0 = compare x y) domain)
let f' domain range y = domain.(find_index (fun x -> 0 = compare x y) range)
There is a better way if you plan on using this on more then just a small set of data. Really, this is a poor implementation for a Map
--this has O(n) lookup, while a map would have O(log(N)). I realize you may not be interested in alternatives, so I will leave my recommendation at that.
There is an if
expression you know, save the match
expression for lists and other data structures so that you don't need to use the unsafe functions List.hd
and List.tl
! For example your code rewrites to (ETA: oops, forgot the recursive call):
let rec f domain range x =
match domain, range with
| k::_, v::_ when k = x -> v
| _::ks, _::vs -> f ks vs x
| _ -> raise Not_found;;
Another approach would be to use the standard library functions:
let f domain range =
let map = List.combine domain range in
fun x -> List.assoc x map;;
精彩评论