2014-02-10 39 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 
相關問題