Let's say I have a discriminated union:
type foo = Bar | Baz | Batz
Then, I want to check how many members of a list are of type Baz
:
List.sumBy (function Bar -> 1 | _ -> 0) foos
Is there a more idiomatic way to do this?
Let's say I have a discriminated union:
type foo = Bar | Baz | Batz
Then, I want to check how many members of a list are of type Baz
:
List.sumBy (function Bar -> 1 | _ -> 0) foos
Is there a more idiomatic way to do this?
请注意,您的示例不正确。它应该是:
List.sumBy (fun x -> match x with Baz -> 1 | _ -> 0) foos
可以重写为:
List.sumBy (function Baz -> 1 | _ -> 0) foos
我认为没有比List.sumBy
在这里使用更惯用的方式了。
这取决于您如何定义“更惯用”。如果它是通过代码性能等因素衡量的语言熟练程度的同义词,那么同样简洁
List.fold (fun sum -> function Baz -> sum + 1 | _ -> sum) 0 foos
List.sumBy
可能被认为更惯用,因为它的执行速度比F# 2.0 以下的版本快 3-4 倍。
List.fold
由于实现专门针对列表进行了高度优化,因此存在非常显着的性能差异,而实现又List.sumBy
回到了Seq.sumBy
通过普通IEnumerable
遍历的地方。
...为了完整起见,不要忘记 for 循环可以进行模式匹配这一鲜为人知的事实。但是,您将收到有关不完整模式匹配的警告,这很烦人。
open System
type foo = Bar | Baz of int | Batz of string * string
let myList = [Bar; Bar; Baz(1); Batz("x", "y"); Baz(2)]
let count =
let mutable acc = 0
for Baz(_) in myList do
acc <- acc + 1
acc
这是我本能地做的。过滤器 |> 长度似乎比求和或折叠更自然。没有检查性能。
let count =
myList
|> List.filter (fun elem -> match elem with | Baz -> true | _ -> false)
|> List.length
我会定义一个count
函数。想要计算满足给定谓词的元素数量是一个非常常见的用例。
let count pred = List.sumBy (fun x -> if pred x then 1 else 0)
利用:
count (fun x -> x = Bar) foos