迭代在ocamlre中构造两个数组之间的函数
问题描述:
我有关于构建一个像这样的函数的问题。迭代在ocamlre中构造两个数组之间的函数
在这里,我有两个表,都具有相同的长度(说长度为n
,那我想情况是满足这一需求的功能:
list1.(0) -> list2.(0)
list1.(1) -> list2.(1)
...
list1.(n-1) -> list2.(n-1)
怎么办呢?我应该做一个函数内部的迭代吗?或者如何追加两个函数(以及如何)?必须有棘手的方法来回答这样的问题
对不起,必须自己回答这个问题,我只是发现这个其实很简单,我可以很容易地创建一个函数f
,这个函数写得非常简短。
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;;
答
从我的理解,你有两个数组。一个定义了函数的范围,另一个范围。你想写一个代表这个函数的ocaml函数。我在这里假设函数是双射的。缺少的部分肉是一个函数,用于查找数组中元素的索引。本着List.find
的精神,我决定通过一个函数来定义这个比较。
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
从这里是微不足道的创造功能,其逆,
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)
有一个更好的方式,如果你打算使用此上更多的则只是一个小的数据集。实际上,对于Map
这是一个糟糕的实现 - 这有O(n)查找,而映射将有O(log(N))。我意识到你可能不会对替代品感兴趣,所以我会留下我的建议。
答
有你知道的if
表达,保存列表等数据结构match
表达,这样你就不需要使用不安全的功能List.hd
和List.tl
!例如你的代码重写为(ETA:哎呀,忘了递归调用):
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;;
另一种方法是使用标准库函数:
let f domain range =
let map = List.combine domain range in
fun x -> List.assoc x map;;
你可以尝试澄清?我不明白你想要构建什么功能 - 只是它有两个相同长度的列表。 – akoprowski 2011-03-08 18:18:51
意识到OCaml中的列表和数组完全不同。 – nlucaroni 2011-03-08 21:09:01
@akoprowski:我想创建一个函数,其中如果list1的第n个参数是输入,我将返回list2的第n个参数。此外,我将使用这个函数作为另一个函数的参数。 – zfm 2011-03-08 22:01:48