将选项类型列表压缩为仅包含非不包含元素的最佳方法?


70

我出乎意料地遇到麻烦,从“选项”列表转到仅包含“某些”元素的列表。

我最初的尝试是:

    let ga = List.filter (fun xx ->
        match xx with
        | Some(g) -> true
        | None -> false) gao 

但是,当然,此结果类型仍然是“选项列表”。我不知道如何使用List.map来压缩它,因为您必须在match语句中处理所有情况。我有一个丑陋的解决方案,但我想知道是否还有更好的方法。

丑陋:

    let rec gOptRemove gdec gacc = 
        match gdec with 
        | head :: tail -> 
            match head with 
            | Some(a) -> gOptRemove tail (a :: gacc)
            | None -> gOptRemove tail gacc
        | [] -> gacc

我宁愿找到一种非递归解决方案,或者找出这种事情的标准方法。

Answers:


153

只是

List.choose id

> [Some 4; None; Some 2; None] |> List.choose id;;
val it : int list = [4; 2]

列表选择

ID


3
哇,那很容易。不知道该功能是否存在。
托尼·彼得森

1
起作用的原因:List.choose想要将an'a变成一个b optionid适用于此,因为它将变成'c option'c option
蒂姆·罗宾逊

4
...哇,那很聪明。这是你的大脑一直在思考的方式吗?
YotaXP

11
只要让类型指导您。您想要一个函数包含option在其签名中,但仅返回一个list(而不是选项列表)。看一下API(msdn.microsoft.com/en-us/library/ee353738.aspx),只有一个这样的函数,choose现在您已经95%了。
Brian

21
嗯,顺便说一句,这似乎是我关于stackoverflow的第1000个答案。我希望这是值得的。:)
Brian

0

另一种方法是使用“选项”模块功能过滤带有值的“选项”,然后创建值列表:

let concreteTypeList =
    optionTypeList
    |> List.filter (fun v -> Option.isSome v)
    |> List.map (fun v -> Option.get v)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.