在 C# LINQ 中,我们可以使用 withlet子句临时变量:
var users2 = from user in users
let total = users.Sum(u => u.Salary)
let avg = total / n
where user.Salary > avg
select user;
Run Code Online (Sandbox Code Playgroud)
是否可以一次性在 F# 中执行相同的操作?
let avg = users |> List.averageBy (fun user -> float user.Salary)
let users2 = users |> List.filter (fun user -> user.Salary > int avg)
Run Code Online (Sandbox Code Playgroud)
我只能通过两次不同的手术来做到这一点。
首先,我认为你的 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 ]
Run Code Online (Sandbox Code Playgroud)
这会在循环avg内部for(或子句内部from)进行计算,因此会为您迭代的每个用户重新计算。您可以通过移动avg之前来改善这一点for:
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 ]
Run Code Online (Sandbox Code Playgroud)
这在单个理解中完成了所有处理并且不会重新计算avg,所以我认为这已经是最好的了。无论您喜欢这个还是明确使用高阶函数都是个人选择 - 我认为您的版本可能比这个更简单。