我们说我有一个受歧视的联盟:
type foo = Bar | Baz | Batz
然后,我想检查列表中有多少类型为Baz
的成员:
List.sumBy (function Bar -> 1 | _ -> 0) foos
是否有更惯用的方式来做到这一点?
答案 0 :(得分:4)
请注意,您的示例不正确。它应该是:
List.sumBy (fun x -> match x with Baz -> 1 | _ -> 0) foos
可以改写为:
List.sumBy (function Baz -> 1 | _ -> 0) foos
我认为这里没有比在这里使用List.sumBy
更加自律的方式。
答案 1 :(得分:3)
这取决于你如何定义“更惯用”。如果它是语言能力的同义词,除了其他因素之外,还有代码表现,那么同样简洁
List.fold (fun sum -> function Baz -> sum + 1 | _ -> sum) 0 foos
可能被认为更加惯用,因为它执行速度比F#2.0下List.sumBy
的版本快3-4倍。
由于List.fold
的实施针对列表进行了高度优化,而List.sumBy
落后于Seq.sumBy
,其中实施通过普通IEnumerable
遍历,因此性能差异非常重要
答案 2 :(得分:0)
我会定义一个count
函数。想要计算满足给定谓词的元素数量是一个非常常见的用例。
let count pred = List.sumBy (fun x -> if pred x then 1 else 0)
使用:
count (fun x -> x = Bar) foos
答案 3 :(得分:0)
这是我本能地做的。过滤|>长度似乎比求和或折叠更自然。没有检查性能。
let count =
myList
|> List.filter (fun elem -> match elem with | Baz -> true | _ -> false)
|> List.length
答案 4 :(得分:0)
...为了完整性,不要忘记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