F# 作为受歧视联合的特定成员的列表元素计数
比如说,我有一个受歧视的联盟:F# 作为受歧视联合的特定成员的列表元素计数,f#,pattern-matching,discriminated-union,F#,Pattern Matching,Discriminated Union,比如说,我有一个受歧视的联盟: type foo = Bar | Baz | Batz 然后,我想检查列表中有多少成员的类型为Baz: List.sumBy (function Bar -> 1 | _ -> 0) foos 有更惯用的方法吗?请注意,您的示例不正确。应该是: List.sumBy (fun x -> match x with Baz -> 1 | _ -> 0) foos 可以改写为: List.sumBy (function Baz -&g
type foo = Bar | Baz | Batz
然后,我想检查列表中有多少成员的类型为Baz
:
List.sumBy (function Bar -> 1 | _ -> 0) foos
有更惯用的方法吗?请注意,您的示例不正确。应该是:
List.sumBy (fun x -> match x with Baz -> 1 | _ -> 0) foos
可以改写为:
List.sumBy (function Baz -> 1 | _ -> 0) foos
我认为没有比在这里使用
List.sumBy
更为自动化的方法了。请注意,您的示例是错误的。应该是:
List.sumBy (fun x -> match x with Baz -> 1 | _ -> 0) foos
可以改写为:
List.sumBy (function Baz -> 1 | _ -> 0) foos
我不认为有比在这里使用
List.sumBy
更具idomatic的方法了。这取决于您如何定义“更惯用”。如果它是语言能力的同义词,除其他因素外,通过代码性能来衡量,那么同样简洁
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
遍历。这取决于您如何定义“更地道”。如果它是语言熟练程度的同义词,除其他因素外,通过代码性能来衡量,那么同样简洁
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
遍历。我将定义一个count
函数计算满足给定谓词的元素数量是一个非常常见的用例
let count pred = List.sumBy (fun x -> if pred x then 1 else 0)
使用:
我将定义一个
count
函数。计算满足给定谓词的元素数量是一个非常常见的用例
let count pred = List.sumBy (fun x -> if pred x then 1 else 0)
使用:
这是我本能地做的。过滤器|>长度似乎比求和或折叠更自然。没有检查性能
let count =
myList
|> List.filter (fun elem -> match elem with | Baz -> true | _ -> false)
|> List.length
这是我本能地做的。过滤器|>长度似乎比求和或折叠更自然。没有检查性能
let count =
myList
|> List.filter (fun elem -> match elem with | Baz -> true | _ -> false)
|> List.length
…对于完整性,请不要忘记一个鲜为人知的事实,即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
开放系统
类型foo=Bar | Baz of int | Batz of string*string
设myList=[Bar;Bar;Baz(1);Batz(“x”,“y”);Baz(2)]
让计数=
设可变acc=0
对于myList do中的Baz(u)
acc…对于完全性,不要忘记一个鲜为人知的事实,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
开放系统
类型foo=Bar | Baz of int | Batz of string*string
设myList=[Bar;Bar;Baz(1);Batz(“x”,“y”);Baz(2)]
让计数=
设可变acc=0
对于myList do中的Baz(u)
acc>count2;;>val-it:int=2>也作为一个控制台应用程序运行,而不仅仅是在FSI中。不完全是——谷歌搜索了一下,这似乎是一个经过深思熟虑的功能,他们在上面加了一个警告,基本上不赞成它。我很喜欢它,但可能这只是我!>count2;;>val-it:int=2>也作为一个控制台应用程序运行,而不仅仅是在FSI中。不确切地说,谷歌搜索一下,这似乎是一个经过深思熟虑的功能,他们在上面加了一个警告,基本上不赞成它。我很喜欢它,但可能这只是我!FTR,原因是列表。这种方式的折叠速度比列表快。sumBy
是因为所有.sum*
函数都被选中>操作符+
@ildjarn:我不这么认为。一个“快速n脏”的实验,用检查的(+)
替换检查的(+)
,在序列中。sumBy
将这个因素视为减速的原因。在一个包含10000000个元素的列表中列表。fold
版本仍然快3-smth倍(Real:00:00.062,CPU:00:00.062,GC-gen0:0,gen1:0,gen2:0
),比未经检查的(+)版本具有List.sumBy
(Real:00:00:00.198,CPU:00:00:00.202,GC-gen0:0,gen1:0,gen2:0
)。啊,你说得对——一点实际测试(想象一下)就我而言,我也得出了同样的结论。+1作为你的答案。FTR,原因是列表。这种方式的折叠比列表快。sumBy
是因为所有。sum*
函数都被选中操作符+
@ildjarn:我不这么认为。一个用替换被选中的的“快速肮脏”实验。(+)未检查(+)
在序列中。sumBy
将此因素视为减速的原因。在一个包含10000000个元素的列表中列表。fold
版本仍然比带有列表的未检查(+)版本快三倍(Real:00:00:00.062,CPU:00:00.062,GC gen0:0,gen1:0,gen2:0
)。sumBy
(Real:00:00:00.198,CPU:00:00.202,GC gen0:0,gen1:0,gen2:0
)。啊,你说得对——我做了一点实际测试(想象一下),得出了相同的结论。你的答案是+1。