TL;DR
“最惯用”的方式可能是@Mark Seemanns:
let count x = Seq.filter ((=) x) >> Seq.length
The TooLong part
请注意,这个函数是完全通用的:x:'a -> (seq<'a> -> int) when 'a : equality
,即它计算任何出现的次数x
在一个序列中'a
s,只要'a
支持平等。由于右侧是一个函数,我们也不需要指定字符串参数。这就是所谓的无点 https://wiki.haskell.org/Pointfree风格。
该函数是通过转动来构造的=
通过将运算符括在括号中将其放入函数中(认为(=)
= fun x y -> x = y
),用这个谓词过滤序列并计算结果seq
s 长度,即
let count x xs =
xs
|> Seq.filter (fun x' -> x' = x)
|> Seq.length
which is
let count x xs =
Seq.length(Seq.filter (fun x' -> x' = x) xs)
当然,您也可以利用“C# 方式”:
let count' x xs = System.Linq.Enumerable.Count(xs, fun x' -> x' = x)
这里你不能只转动相等运算符(=)
转换为谓词,因为 F# 编译器需要施展一些魔法来将 F# 转换为谓词'a -> bool
into a Func<'a, bool>
.
用法完全相同:
count 'a' "abbbac"
或(更易读)
"abbbac" |> count 'a'
"abbac" |> count' 'b'
这(以及更好的可组合性)是函数式程序员倾向于颠倒参数顺序的原因(count x xs
vs. count xs x
).
更奇特(且性能较差)的解决方案:
let count'' (c : char) str =
(System.Text.RegularExpressions.Regex.Matches(str, string c)).Count
let count''' (c : char) str =
(String.length str) - (str.Replace(string c, "") |> String.length)