How to Use flatMap in Swift. Code Examples.
Using mapfilter or reduce to operate on Swift collection types such as Array or Dictionary is something that can take getting used to. Unless you have experience with functional languages your instinct may be to reach for the more familiar for-in loop. With that in mind here is my guide to using mapfilterreduce and flatMap and compactMap.
Use map to loop over a collection and apply the same operation to each element in the collection. The map function returns an array containing the results of applying a mapping or transform function to each item:. This works but the boilerplate code to declare the type of the squares array and then loop over it is a little verbose. We also need to make the squares array a var as we are changing it in the loop. Now compare to when we use map :.
This is a big improvement. Also the squares result is now a let or non-mutating value and we did not even need to declare its type as Swift can infer it. The shorthand closure syntax can make this hard to fujifilm x at first. The map function has a single argument which is a closure a function that it calls as it loops over the collection.
This closure takes the element from the collection as an argument and returns a result. The map function returns these results in an array. The closure has a single argument: value: Double and returns a Double but Swift can infer this.
Also since map has a single argument which is a closure we do not need the and and with a single line closure we can even omit the return :. The in keyword separates the argument from the body steamvr please plug in your vr headset oculus quest the closure.
If you prefer you can go one step further and use the numbered arguments shorthand:. The type of the results is not limited to the type of the elements in the original array. Here is an example of mapping an array of integers to strings:. The map operation is not limited to Arrays you can use it anywhere you have a collection type. For example, use it with a Dictionary or a Setthe result will always be an Array. Here is an example with a Dictionary:. Quick tip: If you have trouble understanding the argument types of the closure Xcode code completion will help you:.
In this case we are mapping a Dictionary so as we iterate over the collection our closure has arguments that are a String and a Double from the types of the key and value that make up each element of the dictionary.
Use filter to loop over a collection and return an Array containing only those elements that match an include condition. The filter method has a single argument that specifies the include condition. This is a closure that takes as an argument the element from the collection and must return a Bool indicating if the item should be included in the result. Use reduce to combine all items in a collection to create a single new value.Swift has a bunch of functions that are useful for transforming collections and sequences.
These higher-order functions are super helpful for transforming collections, in a concise and insightful way. This function applies a transformation to each of the elements in a sequence, like an array or dictionary.
Like this:. Higher-order functions can also output functions, which is useful for a programming paradigm called functional programming. This includes collections like arraysdictionariesand setsranges like The above code starts out with a nested array of integers. The numbers array consists of an array of 3 arrays, that each contains 3 numbers. No transformation or operation is happening. See how giraffes contains an array of arrays?
We only want integers giraffes! Before Swift 4. Since Swift 4. See what happens? This Int initializer is failable : it can return nil — an optional — so its return type is Int? As a result, the return type of the mapping transformation is [ Int? In the above code, the type of result is [ Int ].
And you would have needed an extra step to unwrap the values from the array, to work with them. In general, higher-order functions are useful because they let you apply a function to a sequence of values. Instead of coding the transformation procedurally, you can just apply the function and get a result back. You could, in a music app for example, have 3 arrays: songs, artists and playlists.
You want to construct a timeline of posts for a user. You use 3 queries to select post IDs for the user, for instance from follower posts, advertisements, and trending topics. The first one applies a transformation to a sequence, the second one flattens the resulting array, and the third one removes nil values before returning its result.
Code Swift right in your browser! Go to the Swift Sandbox.
One of the very cool features of the Swift is a Higher Order Function. It has functions like map, flatMap, sort, filter and reduce which can be used on the collection types.
Means optional, but will come to this later. This higher order function loops over a collection and applies the same operation to each element in the collection. We want the collection of all the Person names from this collection. In the traditional development environment, we could have achieved the result by writing code as shown below. Approach Notice how we are getting an array of arrays.
This is probably not what we want. This is because the map is returning the exact type that corresponds to the mapping transformation. When implemented on sequences: Flattens a collection of collections. Say, we have two arrays within an array that we would like to combine into a single array. This is what we are expecting here. NOTE: My observation with flatMap — If the cars array is optional field then it will not give you the single collection of names. We can easily solve this by.
I wanted to understand why this behavior is there and not how to solve it. I have already posted a question on stackoverflow. Special thanks to zneak for answering this.
Answer: For the purpose of map and flatMap optionals are collections of 0 or 1 elements.
You can directly call map and flatMap on optionals without unwrapping them. To illustrate it in a simple way for our understanding it will be treated as shown below.
Stack Overflow for Teams is a private, secure spot for you and your coworkers to find and share information. I can't understand the difference between map and flatMap In RxSwift. In the RxSwift playground examples and the books, flatMap is used as converting Observables which has inner Observable property.
However I see flatMap being used directly on Observable of basic types. For example for below code, both of them produces the same output. Can someone help me to understand the difference between map and flatMap. The example you use is relatively simple, it is simply sending and Observable mapped into something else. Here is quote from Reactive extension documentation.
The FlatMap operator transforms an Observable by applying a function that you specify to each item emitted by the source Observable, where that function returns an Observable that itself emits items. FlatMap then merges the emissions of these resulting Observables, emitting these merged results as its own sequence. This method is useful, for example, when you have an Observable that emits a series of items that themselves have Observable members or are in other ways transformable into Observables, so that you can create a new Observable that emits the complete collection of items emitted by the sub-Observables of these items.
If you extend the example a bit, you will know that flatMap actually transforms each element into a sequence. Now, you can see that map would simply transform a value from sequence and new Observable is created, while flatMap transforms it into sequence. Now, each of the flatMapped elements can themselves emit values since they are stream themselves. To keep it simple Use flatMap when you want return Observable down the stream. Use map is simply transform the value of the observable and pass down the stream.compactMap and flatMap: Clean Up Optionals and Crashes!
Learn more. RxSwift map and flatMap difference Ask Question. Asked 2 years, 6 months ago. Active 1 year, 8 months ago. Viewed 10k times. Meanteacher Meanteacher 1, 2 2 gold badges 12 12 silver badges 33 33 bronze badges. Active Oldest Votes. Here is quote from Reactive extension documentation, The FlatMap operator transforms an Observable by applying a function that you specify to each item emitted by the source Observable, where that function returns an Observable that itself emits items.
Stack Overflow for Teams is a private, secure spot for you and your coworkers to find and share information. I am also following this tutorial. It's on Github in Playground. I would like to keep their Generic approach. AnyObject can contain class and struct i. As commented by dffri, you can use keys property on dictionary which will return LazyMapCollection which will realise only if you access the object inside. Learn more. Swift: flatMap to Dictionary Ask Question.
Asked 4 years, 2 months ago. Active 4 years, 2 months ago. Viewed 6k times. Active Oldest Votes. Khundragpan Khundragpan 1, 1 1 gold badge 10 10 silver badges 21 21 bronze badges. This doesn't print the keys? How do I get the keys as a key and value as Array? Please note in my question, I have a dictionary that I am trying to parse, not an array. In your answer, jsonString is an Array. Sign up or log in Sign up using Google. Sign up using Facebook.
Sign up using Email and Password. Post as a guest Name. Email Required, but never shown. The Overflow Blog.Swift gives us mapcompactMap and flatMap methods, but although they might sound similar they do very different things. In this case, that means taking a number out of an array, doubling it, and putting it back in a new array.
So, this will convert our integer array to a string array:. As a result, converting a string to an integer returns an optional integer. To see this in action, this code uses map to convert a string array into an array of optional integers:. Is it slow to launch or load? Are network requests timing out on the client-side? Are there rendering issues or UI hangs?
Measure and track the quality of your app as perceived by the user. Get started now and ship apps users love. Get started now. Sponsor Hacking with Swift and reach the world's largest Swift community!
So, this line of code does the same string to integer conversion, but results in an array of integers rather than an array of optional integers:. There are lots of places in Swift that return optionals, including try? For example, if you have a UIView and want to read out all subviews that are image views, you can write this:. Or if you have an array of strings and want to know which ones are valid URLs, you can write this:.
So, again: map will take a value out of its container, transform it using the code you specify, then put it back in its container. If you think about it, optionals are similar to arrays: they are also a container with something inside. When we look inside the optional container when we unwrap the optionalwe either find a value or we find nil. This means that the map method also exists on optionals: take the value out of its container an optionaltransform it with a closure we provide, then put it back in the container another optional.
To illustrate this, imagine we had a getUser method that accepts an integer and returns the username with that ID if it exists. That last transformation returned optional integers, so we also looked at how compactMap will perform the same transformation but then unwrap the optionals and discard any nil values.
Then we looked at how map works on optionals: if it has a value it gets unwrapped, transformed, and rewrapped, but if it is nil then it stays as nil. Broadly speaking, any time you see an optional optional anything something has gone wrong and you should rethink. As a result, this code will set result to be Int? Paul Hudson is the creator of Hacking with Swift, the most comprehensive series of Swift books in the world.
He's also the editor of Swift Developer Newsthe maintainer of the Swift Knowledge Baseand a speaker at Swift events around the world. If you're curious you can learn more here. RSS feed.
FlatMap and CompactMap Explained in Swift
Start Here. About Hacking with Swift. Three common functional methods explained. About the author Paul Hudson is the creator of Hacking with Swift, the most comprehensive series of Swift books in the world.
More articles. WWDC Wrap up and recommended talks.What is your biggest struggle right now with building software? I am a big fan of map and flatMapand of the cleaner code that they allow to write. When I realised how easy it was to use map in Swift I fell victim of one of the most common engineer disease: the shiny new thing syndrome.
I started to map everything, and got disappointed at the coffee shop when I couldn't flatMap my espresso with milk to get a flat white. Why even bother having a for loop construct in the language when you can use map?! Once I recovered from my diseased, making arguable coding choices along the way, I realised that map and for deserve the same respect, and serve different purposes.
So here's the rule of thumb on when to use map and when to use for. In the context of Array map get an array, applies a transformation function to every element, and returns a new array with the resulting elements. That's the best use case for map. The cool thing about map is how you can chain multiple transformation together and have code that clearly express what it does. Without going into details an operation has a side effect if it results in some kind of state changing somewhere, for example changing the value of a variable, writing to disk, or updating the UI.
In such case using a for loop is more appropriate. When you need to transform the contents of an array of arrays, into a linear array use flatMap :.
When the code needs to perform some action that has side effects use forand here's a nice trick to avoid nesting:. I run some quick tests and I couldn't see any relevant performance difference between map and a for loop in Swift. The Swift compiler is probably smart enough to use the best performing loop operation regardless of the code we wrote. To recap, here's my rule of thumb: if there's a side effect you probably want to use forotherwise map seems a better fit.
What is your experience with map vs for loops? Do you agree with me or have a different opinion, if so why? Get in touch on Twitter mokagio or leave a comment below. Richard Fox on Twitter and on the comments below points out that Swift provides a forEach method too. The for loop above could be rewritten as:. I left out forEach because in my humble opinion the loop version reads better. For element in array do stuff seems better to me than array for each do stuff.
Nevertheless forEach is as valid Swift as a for loop. You could rewrite all what we've said already using forEach instead of the loop and everything would still stand. It is up to you and your team to decide which convention to use, and choose the appropriate construct depending on what you are trying to achieve.