Suppose I have a list of tupples like these :
[("A",12); ("A",10); ("B",1); ("C",2); ("C",1)]
And I would like to do some kind of groupby
how do I handle that?
In pseudocode-SQL it should look something like this :
SELECT fst(tpl), sum(lst(tpl)) FROM [TupplesInList] GROUP BY fst(tpl)
yielding
[("A",22); ("B",1); ("C",3)]
I could make a Dictionary and add the ints if the key exist, but I can hardly believe that would be the best solution in a language as expressive as F#.
To expand on Johan's answer, I tend to do this sort thing alot and so have made the following generalized function.
let group_fold key value fold acc seq =
seq |> Seq.groupBy key
|> Seq.map (fun (key, seq) -> (key, seq |> Seq.map value |> Seq.fold fold acc))
Which works for your tuple case as seen below
let tuples = [("A",12); ("A",10); ("B",1); ("C",2); ("C",1)]
let regular = group_fold fst snd (+) 0 tuples
let piped = tuples |> group_fold fst snd (+) 0
but will also work with other seqences like a list of strings
let strings = ["A12"; "A10"; "B1"; "C2"; "C1"]
let regular = group_fold (fun (x : string) -> x.[0]) (fun (x : string) -> int x.[1..]) (+) 0 strings
let piped = strings |> group_fold (fun x -> x.[0]) (fun x -> int x.[1..]) (+) 0
One solution:
let tuples = [("A",12); ("A",10); ("B",1); ("C",2); ("C",1)]
tuples
|> Seq.groupBy fst
|> Seq.map (fun (key, values) -> (key, values |> Seq.sumBy snd))
Edit: ...or without piping:
let tuples = [("A",12); ("A",10); ("B",1); ("C",2); ("C",1)]
Seq.map (fun (key, group) -> key, Seq.sumBy snd group)
(Seq.groupBy fst tuples)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With