List 用于设置列表第n个元素的库函数
是否有一个库函数来执行这样的List 用于设置列表第n个元素的库函数,list,ocaml,List,Ocaml,是否有一个库函数来执行这样的set\u elem声明 set_elem (l : int list) (i : int) (x : int) : int list 例如: (set_elem [1; 2; 3; 4] 1 90) 将返回: [1; 90; 3; 4] 不,标准库中没有库函数,但是编写一个库函数并不难 这是一个非尾部递归实现 (** [insert n el lst] inserts element [el] in the [n]th position in the
set\u elem
声明
set_elem (l : int list) (i : int) (x : int) : int list
例如:
(set_elem [1; 2; 3; 4] 1 90)
将返回:
[1; 90; 3; 4]
不,标准库中没有库函数,但是编写一个库函数并不难 这是一个非尾部递归实现
(** [insert n el lst] inserts element [el] in the [n]th position in the
list [lst].
Raises: [Failure] if index is out of bounds *)
let rec insert n el lst =
match n,lst with
| i, _ when i >= List.length lst -> failwith "Index out of Bounds"
| _, [] -> []
| 0, _::t -> el::(insert (-1) el t)
| i, h::t -> h::(insert (i-1) el t)
其思想是将模式匹配与n
和lst
一起进行
如果点击空列表,则返回初始值(如果需要尾部递归解决方案,则返回累加器)
如果n
点击0,则将元素附加到列表中,并继续浏览列表的其余部分以保留其他元素(但请确保不再点击0,这就是我使用-1
的原因)
否则,您将添加列表中的旧元素,直到
n
达到0。或者,如果您希望使用可变数据结构,则数组
模块可以完全做到这一点
let a = [|1; 2; 3; 4|];;
(* val a : int array = [|1; 2; 3; 4|] *)
Array.set a 1 90;;
(* - : unit = () *)
a;;
(* - : int array = [|1; 90; 3; 4|] *)
没有,这可能是因为直接索引对于不可变链表来说是一个非常糟糕的用例,其成本并没有通过这些方便的函数得到适当的反映。如果你发现自己经常这样做,你应该考虑使用数组。 也就是说,我能想到的最简单的方法是使用
List.mapi
仅在索引正确时返回新元素,否则返回现有元素:
List.mapi (fun i el -> if i = 1 then x else el) l
或作为具有所需签名的函数:
let set_elem (l : int list) (i : int) (x : int) : int list =
List.mapi (fun i' el -> if i = i' then x else el) l
其他解决方案在
O(n)
时间内运行(其中n
是列表的长度),而您实际上只需要解决方案在O(i)
时间内运行(其中i
是索引)
下面是一个高效的尾部递归函数:
let set l ~i ~data =
let rec helper ~prev_rev ~curr ~i =
match curr, i with
| [] , _ -> List.rev prev_rev
| _ :: curr, 0 -> List.rev_append prev_rev (data :: curr)
| hd :: curr, _ -> helper ~prev_rev:(hd :: prev_rev) ~curr ~i:(i - 1)
in
if i < 0 || i >= List.length l
then l
else helper ~prev_rev:[] ~curr:l ~i
设置l~i~数据=
让rec helper~prev_rev~curr~i=
搭配咖喱,我喜欢
|[],->List.rev prev\u rev
|当前,0->List.rev\u append prev\u rev(数据:当前)
|hd::curr,->helper~prev\u rev:(hd::prev\u rev)~curr~i:(i-1)
在里面
如果i<0 | | i>=List.length l
然后我
else helper~prev_rev:[]~curr:l~i
如果传入无效索引,此函数不会更改l
。如果愿意,可以更改此项以引发异常