我刚刚在做一个 CodeWars 练习——“创建一个函数,它接受一个非负整数和字符串的列表,并返回一个过滤掉字符串的新列表”。

我的解决方案使用了 List.filter,但在其中一种边缘情况下失败了。所以我查看了他们的解决方案,它使用了 List.choose - 它似乎与我的版本几乎相同,只是它在决定是否将其包含在新列表中之前将结果转换为一个选项。

我很困惑 - 请有人解释什么时候最好使用“选择”,什么时候最好使用“过滤器”?

最佳答案

我认为您已经观察到答案的本质: filter 允许您测试条件,但是使用 choose 您还可以在同一表达式中投影您的值,如果使用 map 则需要单独的 filter

由于问题陈述不清楚(列表不能同时包含整数和字符串,除非它们被装箱;即列表的类型将是 obj list ),我们可以查看这两种情况。请注意使用 map 时附加的 filter 函数。

// List of strings that may contain integer representations
["1"; "abc"; "2"; "def"]
|> List.choose (System.Int32.TryParse >> function
| true, i -> Some i
| _ -> None )

["1"; "abc"; "2"; "def"]
|> List.map System.Int32.TryParse
|> List.filter fst
|> List.map snd

两个表达式都返回 int list = [1; 2]
// List of object that are either of type int or of type string
[box 1; box "abc"; box 2; box "def"]
|> List.choose (function
| :? int as i -> Some i
| _ -> None )

[box 1; box "abc"; box 2; box "def"]
|> List.filter (fun i -> i :? int)
|> List.map unbox<int>

obj list 作为输入的情况下,投影用于提供正确的结果类型。这可能以不同的方式完成,例如带有带注释的 let 绑定(bind)。

最后,两者之间的决定取决于您的个人喜好。

10-07 16:05
查看更多