Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Map with Optional Unwrapping in Swift

Say I had the below api :

func paths() -> [String?] {
    return ["test", nil, "Two"]
}

And I was using this in a method where I needed [String], hence I had to unwrap it using the simple map function. I'm currently doing :

func cleanPaths() -> [String] {
    return paths.map({$0 as! String})
}

Here, the force-cast will cause an error. So technically I need to unwrap the Strings in the paths array. I'm having some trouble doing this and seem to be getting silly errors. Can someone help me out here?

like image 596
gran_profaci Avatar asked Jun 30 '15 21:06

gran_profaci


People also ask

Can we map over optional values?

Map over an optional when the closure returns a non-optional and nil is never needed. Flat map over an optional when the closure could return nil . Whether you map or flat map over an optional, the return value is always an optional.

What is the difference between if let and guard let in Swift?

In if let , the defined let variables are available within the scope of that if condition but not in else condition or even below that. In guard let , the defined let variables are not available in the else condition but after that, it's available throughout till the function ends or anything.

How do I declare optional in Swift?

If you defined a variable as optional, then to get the value from this variable, you will have to unwrap it. This just means putting an exclamation mark at the end of the variable. Optional("Hello, Swift 4!")

How do I unwrap an optional value in Swift?

You must unwrap the value of an Optional instance before you can use it in many contexts. Because Swift provides several ways to safely unwrap optional values, you can choose the one that helps you write clear, concise code. The following examples use this dictionary of image names and file paths:

How do you declare an optional variable in Swift?

You can declare optional variables using an exclamation mark instead of a question mark. Such optional variables will unwrap automatically and you do not need to use any further exclamation mark at the end of the variable to get the assigned value. var mycodetipsString:String! mycodetipsString = "Hello, Swift !"

How do I know if an optional value is implicitly unwrapped?

The only way to find out is to unwrap it. An implicitly unwrapped optional might contain a value, or might not. But it does not need to be unwrapped before it is used. Swift won’t check for you, so you need to be extra careful. Example: String! might contain a string, or it might contain nil – and it’s down to you to use it appropriately.

How do you unwrap an optional variable in Python?

If you know that an optional definitely has a value, you can force unwrap it by placing this exclamation mark after it. If you defined a variable as optional, then to get the value from this variable, you will have to unwrap it. Putting an exclamation mark at the end of the variable.


3 Answers

compactMap() can do this for you in one step:

let paths:[String?] = ["test", nil, "Two"]

let nonOptionals = paths.compactMap{$0}

nonOptionals will now be a String array containing ["test", "Two"].

Previously flatMap() was the proper solution, but has been deprecated for this purpose in Swift 4.1

like image 61
Brad Larson Avatar answered Oct 10 '22 10:10

Brad Larson


You should filter first, and map next:

return paths.filter { $0 != .None }.map { $0 as! String }

but using flatMap as suggested by @BradLarson is a just better

like image 5
Antonio Avatar answered Oct 10 '22 10:10

Antonio


Perhaps what you want to is a filter followed by a map:

func cleanPaths() -> [String] {
    return paths()
            .filter {$0 != nil}
            .map {$0 as String!}
}

let x = cleanPaths()
println(x) // ["test", "two"]
like image 1
Code Different Avatar answered Oct 10 '22 09:10

Code Different