F # сгруппировать более чем в одно значение - PullRequest
0 голосов
/ 24 ноября 2018

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)

Однако мне не удается сгруппировать по двум значениям, скажем Debitorи Creditor.В идеале я хотел бы сгруппировать с учетом Debitor AND Creditor, применяя агрегаторную функцию «Сумма» для свойства Spend.

Другими словами , я быхотел бы получить эквивалент F # следующего запроса LINQ:

 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 голосов
/ 24 ноября 2018
let sumTransactions (transactions: Transaction list) =
    transactions
    |> Seq.groupBy(fun ts -> (ts.Creditor, ts.Debitor))
    |> Seq.map (fun ((cred, deb), ts) -> 
                    let s = ts |> Seq.sumBy (fun t -> t.Spend)
                    Transaction(deb, s , cred))
0 голосов
/ 24 ноября 2018

Вы можете использовать кортеж в качестве ключа группы следующим образом:

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)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...