F# and List manipulations
April 22, 2014 2 Comments
I am preparing for a Beginning F# dojo for TRINUG tomorrow and I decided to do a presentation of Seq.GroupBy, Seq.CountBy, and Seq.SumBy for tuples. It is not apparent by the same the difference among these constructs and I think having a knowledge of them is indispensible when doing any kind of list analysis.
I started with a basic list like so:
- let data = [("A",1);("A",3);("B",2);("C",1)]
I then ran a GroupBy through the REPL and got the following results:
- let grouping = data
- |> Seq.groupBy(fun (letter,number) -> letter)
- |> Seq.iter (printfn "%A")
- ("A", seq [("A", 1); ("A", 3)])
- ("B", seq [("B", 2)])
- ("C", seq [("C", 1)])
I then ran a CountBy through the REPL and got the following results:
- let counting = data
- |> Seq.countBy(fun (letter,number) -> letter)
- |> Seq.iter (printfn "%A")
- ("A", 2)
- ("B", 1)
- ("C", 1)
I then ran a SumBy through the REPL and got the following results:
- let summing = data
- |> Seq.sumBy(fun (letter,number) -> number)
- |> printfn "%A"
- 7
Now the fun begins. I combined a GroupBy and a CountBy through the REPL and got the following results:
- let groupingAndCounting = data
- |> Seq.groupBy(fun (letter,number) -> letter)
- |> Seq.map(fun (letter,sequence) -> (letter,sequence |> Seq.countBy snd))
- |> Seq.iter (printfn "%A")
- ("A", seq [(1, 1); (3, 1)])
- ("B", seq [(2, 1)])
- ("C", seq [(1, 1)])
Next I combined a GroupBy and a SumBy through the REPL and got the following results:
- let groupingAndSumming = data
- |> Seq.groupBy(fun (letter,number) -> letter)
- |> Seq.map(fun (letter,sequence) -> (letter,sequence |> Seq.sumBy snd))
- |> Seq.iter (printfn "%A")
- ("A", 4)
- ("B", 2)
- ("C", 1)
I then combined all three:
- let groupingAndCountingSummed = data
- |> Seq.groupBy(fun (letter,number) -> letter)
- |> Seq.map(fun (letter,sequence) -> (letter,sequence |> Seq.countBy snd))
- |> Seq.map(fun (letter,sequence) -> (letter,sequence |> Seq.sumBy snd))
- |> Seq.iter (printfn "%A")
- ("A", 2)
- ("B", 1)
- ("C", 1)
With this in hand, I created a way of both counting and summing the second value of a tuple, which is a pretty common task:
- let revisedData =
- let summed = data
- |> Seq.groupBy(fun (letter,number) -> letter)
- |> Seq.map(fun (letter,sequence) -> (letter,sequence |> Seq.sumBy snd))
- let counted = data
- |> Seq.groupBy(fun (letter,number) -> letter)
- |> Seq.map(fun (letter,sequence) -> (letter,sequence |> Seq.countBy snd))
- |> Seq.map(fun (letter,sequence) -> (letter,sequence |> Seq.sumBy snd))
- Seq.zip summed counted
- |> Seq.map(fun ((letter,summed),(letter,counted)) -> letter,summed,counted)
- |> Seq.iter (printfn "%A")
- ("A", 4, 2)
- ("B", 2, 1)
- ("C", 1, 1)
Finally, Mathias pointed out that I could use this as an entry to Deddle. Which is a really good idea….
Pingback: F# Weekly #17, 2014 | Sergey Tihon's Blog
Pingback: 5/1/2014 Article Links | The Puntastic Programmer