以下代码将元素插入按升序排序的列表中。
let rec insert x l =
match l with
| [] -> [x]
| y::ys -> if x < y then x::y::ys else y::insert x ys
但是,如何使用List.fold_right实现上述函数,并且没有递归?
答案 0 :(得分:3)
查看List.fold_right
的最简单实现:
let rec fold_right f li init = match li with
| [] -> init
| y::ys -> f y (fold_right f ys init)
您可以尝试类似
的内容let insert x li =
let add_x y inserted_ys =
if x < y then x::y::inserted_ys
else y::inserted_ys
in
List.fold_right add_x li [x]
问题是then
分支不正确:您将在列表的开头和x
中的两个位置获得inserted_ys
。但是,您知道x
列表中的inserted_ys
位置在开头,因为ys
的所有元素都大于x
。因此,您只需使用x
删除List.tl
。
let insert x li =
let add_x y inserted_ys =
if x < y then x::y::(List.tl inserted_ys)
else y::inserted_ys
in
List.fold_right add_x li [x]
注意这是编写insert
的复杂方法。一种更好的技术是让add_x
返回一对列表和一个布尔值,布尔告诉你是否已添加x
。
答案 1 :(得分:1)
我认为解决方案的方案是这样的:
fun insert x l =
List.fold_right (fun a b -> if <test> then a :: x :: b else a :: b) l []
每次调用函数时,它都会看到最终列表的结尾,以及通常在列表前面的新元素。根据此信息,似乎可以决定是否在当前位置插入您的值x
。
此方案的简单实现将在结果中多次插入x。但在我看来,如果你使<test>
足够具体,那将会奏效。
当x属于列表的开头时,此方案也不起作用。你必须单独处理这个案子。
正如加油所说,这不是建立升序清单的有效方法。 (FWIW gasche是比我更知识渊博的OCaml专家: - )