首页 > 解决方案 > F# 按多个值分组并聚合

问题描述

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

type Transaction(Debitor: string, Spend:float, Creditor:string)  = 
     member this.Debitor = Debitor
     member this.Spend = Spend
     member this.Creditor = Creditor

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

let tsGroupDebitor =
    transactions        
    |> Seq.groupBy(fun ts -> ts.Debitor)

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

换句话说,我想实现以下 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
            });

返回匿名类型的 IEnumerable 的位置。

标签: c#linqf#grouping

解决方案


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

let tsGroupDebitor =
    transactions        
    |> Seq.groupBy(fun ts -> (ts.Debitor, ts.Creditor))

如果要聚合每个组的事务以汇总 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)))

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


推荐阅读