将选项列表映射到字符串列表

时间:2015-10-12 15:26:09

标签: functional-programming ocaml

我在OCaml中有以下功能:

let get_all_parents lst = 
  List.map (fun (name,opt) -> opt) lst

使用(name, opt)将我的大列表映射到opt列表。一个选项可以包含NoneSome value,在这种情况下是一个字符串。我想要一个包含所有值的字符串列表。

我是初学者学习OCaml。

3 个答案:

答案 0 :(得分:0)

我要扩大@ Carsten的答案。他指的是正确的方向。

不清楚你问的问题是什么。例如,我不确定您为什么要告诉我们您的功能get_all_parents。可能这个功能是你试图得到你想要的答案,而且它并不适合你。或者您可能对此功能感到满意,但您想对其结果进行进一步处理吗?

无论哪种方式,List.map都无法完成整个工作,因为它总是会返回与其输入长度相同的列表。但是你需要一个可以有不同长度的列表,具体取决于大列表中有多少None个值。

所以你需要一个只能提取你感兴趣的列表部分的函数。正如@Carsten所说,关键函数是List.filter

mapfilter的某种组合肯定会做你想要的。或者您可以使用fold,它具有mapfilter的强大功能。或者你可以编写自己的递归函数来完成所有的工作。

<强>更新

也许您的问题在于从string中提取string option。 &#34;很好&#34;这样做的方法是提供一个默认值,当选项为None时使用

let get default xo =
    match xo with
    | None -> default
    | Some x -> x

# get "none" (Some "abc");;
- : string = "abc"
# get "none" None;;
- : string = "none"
# 

答案 1 :(得分:0)

我认为filtermap一起使用是一个很好的解决方案。这是因为当您应用mapstring option转换为string时,您需要处理None个案。即使知道你没有任何None因为filter将它们删除了,类型检查器也不会,也无法帮助你。如果您启用了非穷举模式匹配警告,您将获得它们,或者您必须为None情况提供某种虚拟字符串。并且,您将不得不希望在以后重构时不会引入错误,或者编写测试用例或进行更多代码审查。

相反,您需要一个函数filter_map : ('a -> 'b option) -> 'a list -> 'b list。我的想法是,这与map类似,但filter_map f lst会将lst评估为f的{​​{1}}的每个元素都删除。如果None评估为f,则结果列表将为Some v。然后你可以像v这样使用:

filter_map

您也可以将其写为

filter_map (fun (_, opt) -> opt) lst

更一般的例子是:

filter_map snd lst

filter_map (fun (_, opt) -> match opt with | Some s -> Some (s ^ "\n") | None -> None) lst 可以像这样实现:

filter_map

编辑为了更完整,您也可以

let filter_map f lst =
  let rec loop acc = function
    | []      -> List.rev acc
    | v::lst' ->
      match f v with
      | None    -> loop acc lst'
      | Some v' -> loop (v'::acc) lst'
  in

  loop [] lst

遗憾的是,这种功能不在标准库中。它出现在Batteries IncludedJane Street Core中。

答案 2 :(得分:0)

str.encode(ciphertext, encoding='utf-8')

结果:

type opt = Some of string | None

List.fold_left (fun lres -> function
    (name,Some value) -> value::lres
  | (name,None)       -> lres
) [] [("s1",None);("s2",Some "s2bis")]