2014-02-10 41 views
1

我写了一个函数来取消整数列表,我想知道是否有更好的方法来写它。ocaml - deoptionalize清单:有没有更简单的方法?

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) 
;; 

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

+0

您使用的是'Core'库? – phimuemue

+0

是的我正在使用核心库 – Gasim

回答

4

我想这是“手工编码”的解决方案(即没有0​​和filter)更容易阅读,但如果你真的需要使用它们,在这里你去:

看来你正在使用的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

我不熟悉'核心',但不应该有'List.choose'函数?见F#的:http://msdn.microsoft.com/en-us/library/ee353456.aspx –

+0

@RamonSnir谢谢,它实际上!它被称为'filter_map'。 – phimuemue

+0

不会filter_map做相反的deoptionalize? 'filter_map fl是l的子列表,仅包含f返回的元素Some e.'(引自https://ocaml.janestreet.com/ocaml-core/109.60.00/doc/core/#Std.List) – Gasim

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 

更清晰和尾递归和性能更好

0

另一种解决方案,

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