Swift Do Something Useful with Zip, Map, and Reduce
Today’s article is the zip, map, and reduce functions in Swift. Let’s walkthrough a typical problem that you might come across in your coding endeavors.
Problem Statement
You work on a school grading app that allows teachers to monitor their students’ progress. You have information on each student in a class along with their grades for assignments and tests. All of this information is stored and can be retrieved in JSON, which means you can ultimately have structured arrays and dictionaries of data.
So far so good. However, your boss wants changes. She has asked you to give teachers more ways to analyze their students’ performance. While this work could be done on the server, she wants to see the functionality done in the client app to minimize network traffic along with a few other reasons for which she didn’t elaborate.
Disclaimer — this is a contrived example and we are going to simplify some of the assumptions to make the problem work with the lessons on zip, map, and reduce.
Let’s look at how we could begin to solve some of these challenges with zip, map, and reduce functions.
Zip
The zip method allows you to work with arrays, sets, dictionaries (or any type that conforms to the SequenceType protocol) to build a SequenceType from two underlying ones. Let’s break that down a bit.
A SequenceType is a protocol that allows a type to use a for…in loop. The built-in collection types are examples of SequenceType. Stepping one level down, the SequenceType protocol defines an associated type named Generator (as a GeneratorType) that is used to provide the iteration capability to get the next Element in the sequence. Putting all of this together, the zip method will create a sequence of pairs where the ith pair is composed of the index values at each of the underlying sequences. Let’s bring it home with an example.
Let’s say you have two arrays that you want to associate with each other. For example, you have an array of student names, and an array of grades that match those students index for index. How could I create a list with the student and grade combined at each index? You guessed it, we could use the zip method to combine them. See the code below.
Map
Each SequenceType has a map method that will iterate over its sequence and call a passed in transform function on each item — collecting and returning the results as a new array. Using the map function, you can convert an array of one type into an array of a different type. See the map method signature that follows:
func map<T>(@noescape _ transform: (Self.Generator.Element)->T) -> [T]
Constraints
Self : _CollectionWrapperType, Self.Index == Self.Base.Index
Extending our example from earlier, we can further format the result of our zip method output to include a letter grade and to convert the results to dictionaries that could be accessed via their keys.
Reduce
The reduce method returns a single result by repeatedly calling each item in the sequence and passing a combine function to accumulate values.
func reduce<T>(_ initial: T, @noescape combine combine: (T, Self.Generator.Element) ->T) -> T
The reduce method is extremely handy when you need to boil a collection of data points into a single value. As an example, it would be interesting to know how many A’s were awarded to our students. See below for an example.
In the code above, we used the reduce method to start with an initial value of zero, and add 1 to our running total each time we find an “A” letter grade.
Final Thoughts
Hopefully, you can see how the zip, map, and reduce methods could be helpful in practice. Each of these methods has roots in functional programming and should lead to you writing cleaner code that is easier to understand and has few lines of code.
On a lighter note, I also wrote an article on why creating native apps is probably the best way to go in most of your mobile development endeavors. Please read that one and weigh in the discussion!
If you find this post helpful, please recommend it for others to read. You can visit me at www.gittielabs.com and subscribe to my RSS feed so that you won’t miss a post. I’m also putting together a video course to teach Swift development and could use your input on topics you feel would be helpful. Thanks for reading!