F# 中 `Seq.distinct` 之后的 `Seq.truncate` 对性能有好处吗

问题描述 投票:0回答:2

在 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 字母。

performance f# sequence distinct truncate
2个回答
0
投票

是的,它提高了性能。

添加此步骤 -

Seq.truncate totalAlphabetCount
可以避免达到目标后不必要的计算。


0
投票

答案是肯定的。我在我的电脑上进行了实证测试,结果如下:

  • 截断:0.0154 毫秒
  • 不截断1150.0毫秒

这样做的原因是,通过调用

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"
© www.soinside.com 2019 - 2024. All rights reserved.