OCaml中对应Python enumerate的最简等价实现方案咨询
关于OCaml中enumerate相关实现的解答
问题1:标准库/Base库是否内置对应功能
- 官方标准库(Stdlib)没有直接返回
(int * 'a) list的同名enumerate函数,但你实现的功能可以通过内置的List.mapi一行完成:
该实现索引从0开始,输出结果和你手写的版本完全一致。let enumerate a_list = List.mapi (fun i x -> (i, x)) a_list - 常用的第三方标准库替代Base/Core中,直接提供了开箱即用的对应函数
List.zip_with_index,直接传入列表即可返回带索引的元组列表,不需要额外封装:# Base.List.zip_with_index ['a'; 'b'; 'c'];; - : (int * char) list = [(0, 'a'); (1, 'b'); (2, 'c')]
问题2:惰性版本enumerate的实现
OCaml生态中常用的惰性序列实现有两类,分别是官方标准库内置的Seq模块、Base库提供的Sequence模块,旧版标准库的Stream模块已被标记为废弃,不推荐使用。
基于官方标准库Seq的实现
Seq是OCaml 4.07之后内置的惰性序列结构,行为和Python的生成器完全一致,你可以直接通过内置高阶函数快速实现:
let enumerate_seq (s: 'a Seq.t) : (int * 'a) Seq.t = Seq.mapi (fun i x -> (i, x)) s
如果要手动写递归实现(不依赖mapi),代码如下,逻辑符合惰性求值规则,只有消费元素时才会计算下一个索引和值:
let enumerate_seq (s: 'a Seq.t) : (int * 'a) Seq.t = let rec helper idx rest () = match rest () with | Seq.Nil -> Seq.Nil | Seq.Cons (elem, next) -> Seq.Cons ((idx, elem), helper (idx + 1) next) in helper 0 s
基于Base库Sequence的实现
Base的Sequence模块直接内置了zip_with_index函数,直接调用即可得到惰性的带索引序列,不需要手动实现:
let enumerate_base_seq (s: 'a Base.Sequence.t) = Base.Sequence.zip_with_index s
注:所有惰性版本的enumerate都不会提前遍历整个序列计算所有元组,只有在你主动消费序列元素(比如迭代、取前N项)时,才会生成对应的索引-值对,内存表现和Python的enumerate完全一致。
内容的提问来源于stack exchange,提问作者Mateo
相关产品推荐
相关产品推荐

