TheSharperDev

Educating about C# and F#

Seq.averageBy - F#

Lets examine Seq.averageBy.

Seq.averageBy: Returns the average of the results generated by applying the function to each element of the sequence. ~ FSharp.Core

Lets say you have an employee type, and a bunch of employees.

type Employee = {
    Name: string;
    StartDate: DateTime;
    Salary: double;
}

let employees = seq {
    { Name = "George"; StartDate = DateTime.Now.AddYears(-3); Salary = 100_000.0};
    { Name = "Bobby"; StartDate = DateTime.Now.AddYears(-1); Salary = 80_000.0};
    { Name = "Susan"; StartDate = DateTime.Now.AddYears(-10); Salary = 1_000_000.0};
    { Name = "Joe"; StartDate = DateTime.Now.AddYears(-2); Salary = 10_000.0};
}

And you wanted to compute the average salary of all your employees. You could use a map:

[<EntryPoint>]
let main argv =
    let salaries = 
        employees 
        |> Seq.map (fun x -> x.Salary)
        |> Seq.average

    printfn "%f" salaries
    0

Prints 297500.0.

Correct answer, but then you’re iterating through your sequence twice. Once to extract the salary, and second to compute the average.

Lets use Seq.averageBy instead:


[<EntryPoint>]
let main argv =
    let salaries = 
        employees 
        |> Seq.averageBy (fun x -> x.Salary)

    printfn "%f" salaries
    0

The same function we were passing into our map function is now just passed into averageBy.

Notes

  • averageBy does share the same limitations of Seq.average and doesn’t support the int type. (See link for full explanation)