Functional Collection Parameters in C#
While talking through my understanding of the Select method which can be applied to collections in C# with a colleague, it became clear that C# doesn't seem to use the same names for these type of operations as are used in the world of functional programming.
Coincidentally on the same day I came across Bill Six's post about using functional collection parameters in Ruby, so I thought I'd see what the equivalent operations are in C#.
Map
Map evaluates a high order function on all the elements in a collection and then returns a new collection containing the results of the function evaluation.
In C# we can use the 'Select' method. For example, to capitalise all the items in a list:
1 2 | var someValues = new List<string> {"mark", "sydney", "sunny"}; var upperCaseValues = someValues.Select(item => item.ToUpper()); |
The responsibility for iterating the collection has been taken away from me and I can just focus on what I want to do with the collection rather than worrying too much about the details. A more declarative approach.
If I want to see the results of that operation I just do the following:
1 | upperCaseValues.ForEach(Console.WriteLine); |
MARK SYDNEY SUNNY
Filter
Filter applies a predicate against all of the elements in a collection and then returns a collection of elements which matched the predicate.
Conveniently there is actually a built in delegate called 'Predicate' which when combined with the 'FindAll' method can be used to solve this problem.
1 2 3 | var someValues = new List<string> {"mark", "sydney", "sunny"}; var valuesWithSIn = someValues.FindAll(item => item.Contains("s")); valuesWithSIn.ForEach(Console.WriteLine); |
sydney sunny
If we just want the first value in the collection that matches the predicate we would use the 'Find' method instead:
1 2 3 | var someValues = new List<string> {"mark", "sydney", "sunny"}; var valueWithSIn = someValues.Find(item => item.Contains("s")); Console.WriteLine(valueWithSIn); |
sydney
Reduce
Reduce applies a high order function against all the elements in a collection and then returns a single result.
We can use the 'Aggregate' method to achieve this:
1 2 3 | var someValues = new List<string> {"mark", "sydney", "sunny"}; var valuesConcatenated = someValues.Aggregate("",(accumulator, item) => accumulator + item); Console.WriteLine(valuesConcatenated); |
marksydneysunny
The "" passed in as the first parameter to 'Aggregate' is the initial value for the accumulator.
Combining expressions
As with Ruby we can chain these expressions together to return even greater results.
For example, to get concatenate all the items which contain an s we would do the following:
1 2 3 4 | var someValues = new List<string> {"mark", "sydney", "sunny"}; var valuesConcatenated = someValues.FindAll(item => item.Contains("s")) .Aggregate("",(accumulator, item) => accumulator + item); Console.WriteLine(valuesConcatenated); |
sydneysunny
Overall
I really like having this high order functions available to us – it has taken away the need to write some of the most boring code that we used to have to write and makes our code more concise and easier to read.
Nice post, Mark.
I wasn't aware of the aggregate function before, never had a need to use it. But now that I see it…
Richard Banks
18 Dec 08 at 5:43 pm
[...] having to manually perform operations on collections in Java rather than having the selection of functional operators that are available in C# [...]
Coding Dojo #5: Uno at Mark Needham
8 Jan 09 at 11:48 pm
[...] wrote a post about a month ago on using functional collection parameters in C# and over the weekend Fabio and I decided to try and contrast the way you would do this in [...]
F# vs C# vs Java: Functional Collection Parameters at Mark Needham
19 Jan 09 at 7:27 pm
[...] wrote about a month or so ago about the functional collection parameters now available in C# and certainly one of the most fun refactorings for me is trying to get code [...]
C#: Refactoring to functional collection parameters at Mark Needham
3 Feb 09 at 7:20 am
[...] of the interesting cases where I've noticed we tend to avoid functional collection parameters in our code base is when there's the possibility of the collection being [...]
Functional Collection Parameters: Handling the null collection at Mark Needham
16 Jun 09 at 9:07 pm
[...] written previously about the ways I've been making use of functional collection parameters in my code but what I hadn't really considered was that the way [...]
Functional Collection Parameters: A different way of thinking about collections at Mark Needham
18 Jun 09 at 9:54 pm