# F# and List manipulations

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:

1. let data = [("A",1);("A",3);("B",2);("C",1)]

I then ran a GroupBy through the REPL and got the following results:

1. let grouping = data
2.                 |> Seq.groupBy(fun (letter,number) -> letter)
3.                 |> Seq.iter (printfn "%A")

1. ("A", seq [("A", 1); ("A", 3)])
2. ("B", seq [("B", 2)])
3. ("C", seq [("C", 1)])

I then ran a CountBy through the REPL and got the following results:

1. let counting = data
2.                 |> Seq.countBy(fun (letter,number) -> letter)
3.                 |> Seq.iter (printfn "%A")

1. ("A", 2)
2. ("B", 1)
3. ("C", 1)

I then ran a SumBy through the REPL and got the following results:

1. let summing = data
2.                 |> Seq.sumBy(fun (letter,number) -> number)
3.                 |> printfn "%A"

1. 7

Now the fun begins.  I combined a GroupBy and a CountBy through the REPL and got the following results:

1. let groupingAndCounting = data
2.                         |> Seq.groupBy(fun (letter,number) -> letter)
3.                         |> Seq.map(fun (letter,sequence) -> (letter,sequence |> Seq.countBy snd))
4.                         |> Seq.iter (printfn "%A")

1. ("A", seq [(1, 1); (3, 1)])
2. ("B", seq [(2, 1)])
3. ("C", seq [(1, 1)])

Next I combined a GroupBy and a SumBy through the REPL and got the following results:

1. let groupingAndSumming = data
2.                             |> Seq.groupBy(fun (letter,number) -> letter)
3.                             |> Seq.map(fun (letter,sequence) -> (letter,sequence |> Seq.sumBy snd))
4.                             |> Seq.iter (printfn "%A")

1. ("A", 4)
2. ("B", 2)
3. ("C", 1)

I then combined all three:

1. let groupingAndCountingSummed = data
2.                                 |> Seq.groupBy(fun (letter,number) -> letter)
3.                                 |> Seq.map(fun (letter,sequence) -> (letter,sequence |> Seq.countBy snd))
4.                                 |> Seq.map(fun (letter,sequence) -> (letter,sequence |> Seq.sumBy snd))
5.                                 |> Seq.iter (printfn "%A")

1. ("A", 2)
2. ("B", 1)
3. ("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:

1. let revisedData =
2.     let summed = data
3.                     |> Seq.groupBy(fun (letter,number) -> letter)
4.                     |> Seq.map(fun (letter,sequence) -> (letter,sequence |> Seq.sumBy snd))
5.     let counted = data
6.                     |> Seq.groupBy(fun (letter,number) -> letter)
7.                     |> Seq.map(fun (letter,sequence) -> (letter,sequence |> Seq.countBy snd))
8.                     |> Seq.map(fun (letter,sequence) -> (letter,sequence |> Seq.sumBy snd))
9.     Seq.zip summed counted
10.                     |> Seq.map(fun ((letter,summed),(letter,counted)) -> letter,summed,counted)
11.                     |> Seq.iter (printfn "%A")

1. ("A", 4, 2)
2. ("B", 2, 1)
3. ("C", 1, 1)

Finally, Mathias pointed out that I could use this as an entry to Deddle.  Which is a really good idea….