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

Functional programming 将选项列表映射到字符串列表,functional-programming,ocaml,Functional Programming,Ocaml,我在OCaml中具有以下功能: let get_all_parents lst = List.map (fun (name,opt) -> opt) lst 这将我的带有(name,opt)的大列表映射为一个opt列表。选项可以包含None或某个值,在本例中,该值为字符串。我想要一个包含所有值的字符串列表 我是一名学习OCaml的初学者。我将进一步介绍@Carsten的答案。他给你指明了正确的方向 不清楚你在问什么问题。例如,我不知道你为什么要告诉我们你的函数get\u all\u

我在OCaml中具有以下功能:

let get_all_parents lst = 
  List.map (fun (name,opt) -> opt) lst
这将我的带有
(name,opt)
的大列表映射为一个
opt
列表。选项可以包含
None
某个值,在本例中,该值为字符串。我想要一个包含所有值的字符串列表


我是一名学习OCaml的初学者。

我将进一步介绍@Carsten的答案。他给你指明了正确的方向

不清楚你在问什么问题。例如,我不知道你为什么要告诉我们你的函数
get\u all\u parents
。这个函数可能是你试图得到你想要的答案,但它对你来说并不太有效。或者你对这个函数很满意,但是你想对它的结果做进一步的处理

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

因此,您需要一个函数,该函数只能提取您感兴趣的列表部分。正如@Carsten所说,这项工作的关键功能是
List.filter

map
filter
的某些组合肯定会满足您的需求。或者您可以使用
折叠
,它既有
映射
的功能,又有
过滤器
的功能。或者您可以编写自己的递归函数来完成所有工作

更新

可能您的问题是从
字符串选项
中提取
字符串
。执行此操作的“好”方法是提供一个默认值,以便在选项为
None
时使用:

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

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

我不认为将
过滤器
映射
一起使用是解决这个问题的好办法。这是因为当您应用
map
string选项
转换为
string
时,您将需要处理
None
案例。即使你知道你不会有任何
None
s,因为你过滤掉了它们,类型检查器也不会,也帮不了你。如果启用了非穷举模式匹配警告,则会得到它们,或者必须为
None
情况提供某种伪字符串。而且,您必须希望在以后重构时不要引入错误,或者编写测试用例或进行更多的代码审查

相反,您需要一个函数
filter\u map:('a->'b option)->'a list->'b list
。其思想是,这类似于
map
,除了
filter\u map f lst
会删除
lst
的每个元素,而
f
的计算结果为
None
。如果
f
的计算结果为
Some v
,则结果列表将具有
v
。然后您可以像这样使用
filter\u 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\u 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
编辑为了更完整,您也可以

let filter_map f lst =
  List.fold_left (fun acc v ->
    match f v with
    | Some v' -> v'::acc
    | None    -> acc) [] lst
  |> List.rev
很遗憾,这种函数不在标准库中。它在和中都存在

结果:

- : string list = ["s2bis"]

搜索<代码>列表。过滤器
;)谢谢,但是List.filter如何将opt值转换为字符串值呢?您能否提供一个示例:D?
列表。过滤器不进行转换,只进行选择。但是
List.map
进行转换(但不选择)。这就是为什么需要合并它们。这与参数列表的顺序相反,因此如果用户不希望这样,您应该对折叠的结果应用
list.rev
。请您解释一下为什么该代码会回答这个问题?代码唯一的答案是,因为他们不教解决方案。(老实说,即使不知道OCaml,它本身看起来至少有点像样,但有人确实标记了它……)首先,novalain必须告诉我们这个代码是好是坏。
- : string list = ["s2bis"]