为什么Seq.isEmpty说不够元素?

Mic*_*Leo 4 f#

当我鼠标移动时,nums确实是int的seq.知道发生了什么事吗?此函数行旨在等效于C#的DefaultIfEmpty Linq函数.

一般的想法是采用空格分隔的字符串行,并写出哪些出现次数.

在此输入图像描述

码:

    open System

[<EntryPoint>]
let main argv = 
    let tests = Console.ReadLine() |> int
    for i in [0..tests] do
        let (length, count) = Console.ReadLine() 
                                |> (fun s -> s.Split [|' '|])
                                |> (fun split -> Int32.Parse(split.[0]), Int32.Parse(split.[1]))
        Console.ReadLine() 
            |> (fun s -> s.Split [|' '|])
            |> Seq.map int 
            |> Seq.take length
            |> Seq.groupBy (fun x -> x)     
            |> Seq.map (fun (key, group) -> key, Seq.sum group)
            |> Seq.where (fun (_, countx) -> countx = count)
            |> Seq.map (fun (n, _) -> n)
            |> (fun nums -> if Seq.isEmpty nums then "-1" else String.Join(" ", nums))
            |> Console.WriteLine

    0 // return an integer exit code
Run Code Online (Sandbox Code Playgroud)

样品输入:
3
9 2
4 5 2 5 4 3 1 3 4

The*_*ght 9

因此,F#中的序列使用延迟评估.这意味着,当您使用的功能,例如map,where,take等的结果不会立即进行评估.

仅在实际枚举序列时才评估结果.当你调用时Seq.isEmpty,触发一个调用MoveNext(),导致结果序列的第一个元素被评估 - 在你的情况下,这导致一个大的函数链被评估.

在这种情况下,Seq.take如果序列没有足够的元素,则实际上会触发InvalidOperationException .这可能会让您感到惊讶,您来自C#,其中Enumerable.Take将占用所请求的元素数量,但如果到达序列的末尾可能会减少.

如果您想在F#中使用此行为,则需要替换Seq.takeSeq.truncate.