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
,所以我认为这已经很好了。您是喜欢这个还是显式使用高阶函数是个人选择 - 我认为您的版本可能比这个更简单。
在 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
,所以我认为这已经很好了。您是喜欢这个还是显式使用高阶函数是个人选择 - 我认为您的版本可能比这个更简单。