首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >将列表中的所有n项替换为给定的列表- ocaml

将列表中的所有n项替换为给定的列表- ocaml
EN

Stack Overflow用户
提问于 2022-05-26 12:20:27
回答 1查看 101关注 0票数 0

示例remplace_par_liste 2 [-4;-5] [1;2;3;2;2;9] --> [1;-4;-5;3;-4;-5-4;-5;9]

我知道如何处理发生的事情,但不知道如何处理清单。

示例remplace 2 0 [1;2;3;2;2;9] --> [1; 0; 3; 0; 0; 9]

代码语言:javascript
运行
复制
let listere = [1;2;3;2;2;9];;

let rec remplace n p liste = match liste  with

[] -> []

|a::q -> (if a = n then p else a)::(remplace n p q);;

remplace 2 0 listere;;

- : int list = [1; 0; 3; 0; 0; 9] 

问题是,我需要另一个函数来将列表l1插入到列表中?

代码语言:javascript
运行
复制
let listerel = [1;2;3;2;2;9];;

let l1 = [-4;-5];;

let rec remplace_par_liste n l1 liste = match liste with

[] -> []

(|a::q -> (if a = n then l1 else a)::(remplace_par_liste n l1 q);;)

remplace_par_liste 2 l1 listerel;;

File "", line 4, characters 113-114:

Error: This expression has type int list
       but an expression was expected of type int```
EN

回答 1

Stack Overflow用户

发布于 2022-05-26 16:16:50

我建议你先定义第二个函数。

::将允许我们在列表尾部递归运行函数所创建的列表前面添加x

@会让我们连接两个列表,这样我们就可以将替代列表中的值插入到结果中。

代码语言:javascript
运行
复制
let rec replace_value_with_list v sub lst =
  match lst with
  | [] -> []
  | x::xs when x <> v -> x :: replace_value_with_list v sub xs
  | x::xs -> sub @ replace_value_with_list v sub xs

第一个函数则要简单得多,它只是第二个函数的一个专门应用程序,将单个值放入列表中。

代码语言:javascript
运行
复制
let replace_value v sub lst =
  replace_value_with_list v [sub] lst

这种实现的不利因素

我已决定编辑,以提及这一基础上的评论。以上不是尾递归.每次调用函数时,它都占用一定的堆栈空间。堆栈是有限的。递归调用一个或多个函数会导致堆栈溢出错误。

OCaml (和其他一些编程语言,主要是功能方面的语言)提供了尾叫优化。如果编译器能够确定一个函数做的最后一件事是调用自己还是另一个函数,那么调用者在堆栈上占用的空间就可以被重用。

我们可以从ealier修改现有的函数。

当x

replace_value_with_list v -> x ::replace_value_with_list v sub x::xs -> sub @ replace_value_with_list v sub时,让rec replace_value_with_list v sub = match lst与x [] -> [] xs::xs <> v-> x::xs ->sub@replace_value_with_list sub xs匹配。

例如,此操作使函数非尾递归:

x ::replace_value_with_list诉sub

首先我们必须调用replace_value_with_list v sub xs,然后将x添加到它的前面。我们可以通过传递建立列表的累加器来解决这个问题。我们可以使用一个局部辅助函数来隐藏这个细节。由于本地函数正在处理递归,因此不再需要将replace_value_with_list标记为递归。

代码语言:javascript
运行
复制
let replace_value_with_list v sub lst =
  let rec aux v sub lst acc =
    match lst with
    | [] -> List.rev acc
    | x::xs when x <> v -> aux v sub xs (x :: acc)
    | x::xs -> replace_value_with_list v sub xs (sub @ acc)
  in
  aux v sub lst []

请注意,当我们调用aux函数时,它将按照我们期望的方式以相反的顺序构建累加器,因此我们需要在退出条件下反转累加器。

但是,这仍然不是最优的,因为执行连接的@操作符不是尾递归的。我们可以通过将@替换为尾部递归的List.rev_append来克服这一问题。

代码语言:javascript
运行
复制
let replace_value_with_list v sub lst =
  let rec aux v sub lst acc =
    match lst with
    | [] -> List.rev acc
    | x::xs when x <> v -> aux v sub xs (x::acc)
    | x::xs -> aux v sub xs (List.rev_append sub acc)
  in
  aux v sub lst []

这个迭代列表和积累值的过程就是折叠真正发光的地方。

代码语言:javascript
运行
复制
let rvl v sub lst =
  List.(
    let f acc x = if x <> v then x::acc else rev_append sub acc in
    fold_left f [] lst |> rev
  )
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72391727

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档