我对构建这样的函数有疑问。
在这里,我有两个列表,两个都有相同的长度(比如长度为n
,我想要的是一个满足这个要求的函数:
list1.(0) -> list2.(0)
list1.(1) -> list2.(1)
...
list1.(n-1) -> list2.(n-1)
怎么做?我应该在函数内部进行迭代(以及如何)?或附加两个功能(以及如何)?必须有一些棘手的方法来回答这样的事情。
抱歉,我必须自己回答这个问题。我发现这实际上非常简单。我可以很容易地创建一个由nlucaroni编写的函数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;;
答案 0 :(得分:2)
据我了解,你有两个阵列。一个定义了函数的域,另一个定义了范围。你想写一个代表这个函数的ocaml函数。我假设这个函数是双射的。缺少的部分,meat,是一个查找数组中元素索引的函数。本着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))。我意识到你可能对替代品不感兴趣,所以我会留下我的建议。
答案 1 :(得分:2)
您知道有一个if
表达式,保存列表和其他数据结构的match
表达式,这样您就不需要使用不安全函数List.hd
和{{1 }}!例如,您的代码重写为(ETA:oops,忘记了递归调用):
List.tl
另一种方法是使用标准库函数:
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;;