ocaml - deoptionalize list:有更简单的方法吗?

时间:2014-02-10 10:42:45

标签: ocaml

我已经写了一个函数来取消整数列表,我想知道是否有更好的方法来编写它。

let deoptionalize (lst:'a option list) : 'a list =
    List.map ~f:(fun x -> match x with Some x -> x | None -> assert false)
                    (List.filter ~f:(fun x -> x <> None) lst)
;;

在我正在使用的作业中,使用地图和过滤器是必须的。

3 个答案:

答案 0 :(得分:4)

我认为“手动编码”解决方案(即没有mapfilter)更容易阅读,但如果您真的需要使用它们,请转到:

您似乎正在使用Core库。如果是这样,我认为你的解决方案并不是那么糟糕,但可以写得更紧凑:

let deoptionalize lst = 
    List.filter ~f:(is_some) lst
    |> List.map ~f:(function | Some x -> x | None -> assert false)

如果您不介意警告(我不鼓励您这样做),您甚至可以省略更多:

let deoptionalize lst = 
    List.filter ~f:(is_some) lst
    |> List.map ~f:(fun (Some x) -> x)

实际上,Core提供了filter_map(感谢@Ramon Snir的提示),它结合了两者,因此您可以使用:

let deopt lst = 
    List.filter_map ~f:(fun x -> x) lst;;

答案 1 :(得分:2)

在你的情况下,我更喜欢这样做:

let deoptionalize l =
  let rec deopt acc = function
    | [] -> List.rev acc
    | None::tl -> deopt acc tl
    | Some x::tl -> deopt (x::acc) tl
  in 
  deopt [] l

它更清晰,尾递归,性能更好

答案 2 :(得分:0)

另一种解决方案,

let deoptionalize l = 
    List.concat  @@ List.map (function | None -> [] | Some x -> [x]) l