F# 按多个值进行分组并聚合

ale*_*a87 5 c# linq f# grouping

F#。transactions我有以下类型的列表:

type Transaction(Debitor: string, Spend:float, Creditor:string)  = 
     member this.Debitor = Debitor
     member this.Spend = Spend
     member this.Creditor = Creditor
Run Code Online (Sandbox Code Playgroud)

我知道如何按一个值进行分组。举例来说,我想对每个属性进行分组Debitor,很容易使用该属性作为组的键:

let tsGroupDebitor =
    transactions        
    |> Seq.groupBy(fun ts -> ts.Debitor)
Run Code Online (Sandbox Code Playgroud)

Debitor但是,我无法设法按两个值(例如和)进行分组Creditor。理想情况下,我想考虑DebitorAND进行分组Creditor,同时为该Spend属性应用聚合器函数“Sum”。

换句话说,我想实现与以下 LINQ 查询等效的 F#:

 var transactions_GroupSameDebitorCreditor = 
     transactions
     .GroupBy(ts => new { ts.Debitor, ts.Creditor }) // group by multiple values
     .Select(gr => new 
            {
                Debitor = gr.Key.Debitor,
                Debit = gr.Sum(trans => trans.Spend), //sum the trans values per grouped relationships
                Creditor = gr.Key.Creditor
            });
Run Code Online (Sandbox Code Playgroud)

返回匿名类型的 IEnumerable。

Yac*_*sad 6

您可以使用元组作为组键,如下所示:

let tsGroupDebitor =
    transactions        
    |> Seq.groupBy(fun ts -> (ts.Debitor, ts.Creditor))
Run Code Online (Sandbox Code Playgroud)

如果你想聚合每个组的交易来求和 Spend 属性,你可以这样做:

let tsGroupDebitor =
        transactions        
        |> Seq.groupBy(fun ts -> (ts.Debitor, ts.Creditor))
        |> Seq.map(fun ((debitor, creditor), values) -> ( debitor, creditor, values |> Seq.sumBy (fun t -> t.Spend)))
Run Code Online (Sandbox Code Playgroud)

请注意我如何使用模式匹配((debitor, creditor), values)来访问组密钥的两个部分以及每个组的事务序列 ( values)