我刚刚在做一个 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)。最后,两者之间的决定取决于您的个人喜好。