F#通过多个值进行分组并汇总

时间:2018-11-24 17:21:30

标签: 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

我知道如何按一个值分组。举例来说,我想按属性Debitor进行分组,可以轻松地将该属性用作该组的键:

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

但是,我无法按两个值分组,例如DebitorCreditor。理想情况下,我想为Debitor属性应用聚合函数“ Sum”的同时考虑CreditorSpend

换句话说,我想实现与以下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。

2 个答案:

答案 0 :(得分:3)

您可以像这样使用元组作为组键:

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)的交易顺序

答案 1 :(得分:1)

private void btnLoadScores_Click(object sender, RoutedEventArgs e)
        {
            scoremdwList = new List<ScoreMdw>();

        try
        {
            conn.Open();

            List<string> headers = so.GetContentmentHeaders();

            foreach (string header in headers)
                txtHeader.Text += header + "\t";

            scoremdwList = so.GetScoreMdwList();
            lbScores.ItemsSource = scoremdwList;
        }

        catch(Exception ex)
        {
            MessageBox.Show(ex.Message);
        }

        finally
        {
            conn.Close();
        }
    }