我有两排,国家和收入.有多个行具有相同的状态,但我希望每个状态有一行.因此,我希望按州平均所有收入数据,因此我可以得到每个州的平均值,每个州只能获得一个值/行.这是我尝试通过State行对Income行中的值进行平均.我把序列分组如下:
Seq.groupBy(有趣的行 - > row.State)
但是,当我尝试对已经按州(从上面)分组的收入列中的数据进行平均时:
Seq.average(有趣的行 - > row.Income)
它给了我这个错误:
"错误FS0001:期望支持运算符'+'的类型,但是给定了一个函数类型.你可能缺少一个函数的参数."
我做错了什么?
如果你想传递一个函数,你想要Seq.averageBy,而不是Seq.average.Seq.average取一个数字序列,然后Seq.averageBy取一个函数和一个T类型的事物序列(该函数应该是一个取T类型并返回数字的函数).
此外,如果您Seq.groupBy首先使用,请注意它返回一系列元组,其中元组的第一个元素是键,第二个元素是具有该键的值序列.(在类型签名中,这由类型表示seq<'Key * seq<'T>>).所以你想要的是有点复杂,我将引导你完成它:
rows |> Seq.averageBy(fun row -> row.Income).但首先,你正在调用Seq.groupBy,它会返回一系列元组.如果你这样做rows |> Seq.groupBy (fun row -> row.State) |> Seq.averageBy (fun row -> row.Income),那么你会得到一个错误,说元组没有一个叫做的属性Income.因为Seq.groupBy调用已将您的数据转换为以下内容:
seq {
(TX, seq { row1, row4, row7 })
(CA, seq { row2, row5, row8 })
(NY, seq { row3, row6, row9 })
}
Run Code Online (Sandbox Code Playgroud)你最终想要的是:
seq {
(TX, 12345.0)
(CA, 34567.0)
(NY, 23456.0)
}
Run Code Online (Sandbox Code Playgroud)因此,你要的是把所产生的序列Seq.groupBy和变换中,保持了密钥,但变换值的序列的方式吧.每当你想"我想保留这个序列但将其内容变成其他东西"时,你想要的Seq.map.
Seq.map采用一个函数,它接受一个类型为T的项(无论T可能是什么),但是我们可以在函数参数中使用解构(addOneToTuple在该页面上查找示例)以使其更简单:因为我们知道"外部"序列我们映射是一个元组(key, values),我们可以写函数来取一个(key, values)元组:fun (key, values) -> key, (values |> Seq.averageBy ...)将是你想要的.因此,您要使用的管道,首先分组然后平均每个组中的值(同时保持组键)将如下所示:
rows
|> Seq.groupBy (fun row -> row.State)
|> Seq.map (fun (state, groupedRows) ->
let averageIncome = groupedRows |> Seq.averageBy (fun row -> row.Income)
(state, averageIncome))
Run Code Online (Sandbox Code Playgroud)这应该做到这一点.请注意,在最后Seq.map一步中,我必须确保返回一个元组(state, averageIncome); 如果我刚刚返回结果groupedRows |> Seq.averageBy (fun row -> row.Income),那么我会将一个元组映射到单个值,你会得到一个不再有状态的平均收入的seq.
我希望这可以帮助您了解如何在F#中解决像这样的问题.有许多不同的函数可用于列表或序列等集合,起初可能有点令人困惑.但无论您是初学者还是经验丰富的F#开发人员,基本方法都是一样的:您首先要说的是"我拥有什么样的数据,以及我完成后想要获得哪种数据?" 然后你找一个具有正确"形状"的函数将A类数据转换为B类数据; 如果没有单一的功能,你可以将几个功能(如构建块)放在一起,以获得所需的整体功能.(例如,如何我们结合Seq.map和Seq.averageBy这里).
| 归档时间: |
|
| 查看次数: |
107 次 |
| 最近记录: |