# 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