在 Pangram 练习的解决方案中:
let totalAlphabetCount = 1 + int ('Z' - 'A')
let isPangram (input: string): bool =
input
|> Seq.filter System.Char.IsAsciiLetter
|> Seq.map System.Char.ToUpper
|> Seq.distinct
|> Seq.truncate totalAlphabetCount
|> Seq.length = totalAlphabetCount
Seq.truncate totalAlphabetCount
是否可以提高大量输入的性能?
例如,我们有一个 1Gb 字符串,前一百个字符都是 ASCII 字母。
是的,它提高了性能。
添加此步骤 -
Seq.truncate totalAlphabetCount
可以避免达到目标后不必要的计算。
答案是肯定的。我在我的电脑上进行了实证测试,结果如下:
这样做的原因是,通过调用
Seq.truncate
,一旦计算到 26 个不同的字符(这发生在输入的前 100 个左右字符中),Seq.distinct
将停止迭代。如果不调用 Seq.truncate
,Seq.distinct
必须继续在整个字符串中查找不同的字符,即使我们知道其他字符不可能存在。
测试代码:
let rng = Random(0)
let randomChar _ =
rng.Next(32, 128)
|> char
let randomString len =
Array.init len randomChar
|> String
let str =
randomString 1_000_000_00
let test () =
isPangram str |> ignore
test () // warmup
Seq.init 10 (fun _ ->
let stopwatch = Stopwatch.StartNew()
test ()
stopwatch.Elapsed.TotalMilliseconds)
|> Seq.average
|> printfn "%A"