F# 在管道运算符 aka C# LINQ let 中使用临时变量

F# using a temporary variable in pipe operator aka C# LINQ let

在 C# LINQ 中,我们可以使用带有 let 子句的临时变量:

var users2 = from user in users
             let total = users.Sum(u => u.Salary)
             let avg = total / n
             where user.Salary > avg
             select user;

是否可以在 F# 中一次完成相同的操作?

let avg = users |> List.averageBy (fun user -> float user.Salary)
let users2 = users |> List.filter (fun user -> user.Salary > int avg)

我只能在两个不同的操作中做到这一点。

首先,我认为你的F#解决方案是完全合理的,我认为它不需要任何改进。此外,您还希望只预先计算一次 avg - C# 代码很可能会为其调查的每个用户重新计算一次(因此,如果在查询之前计算 avg ,您的 C# 代码会更好! )

C# 查询理解大致等同于以下 F# 序列表达式:

let users2 = 
  [ for u in users do 
    let avg = users |> List.averageBy (fun user -> float user.Salary)
    if u.Salary > int avg then yield u ]

这会在 for 循环内(或在 from 子句内)计算 avg,因此会为您迭代的每个用户重新计算。您可以通过在 for:

之前移动 avg 来改善这一点
let users2 = 
  [ let avg = users |> List.averageBy (fun user -> float user.Salary)
    for u in users do 
      if u.Salary > int avg then yield u ]

这会在一次理解中完成所有处理,并且不会重新计算 avg,所以我认为这已经很好了。您是喜欢这个还是显式使用高阶函数是个人选择 - 我认为您的版本可能比这个更简单。