0

How can I safety unwrap the first optional item from arrayOfStrings to get just the pounds with a default value of 0 using coalescing unwrapping?

Based on the code below, what I want is to be able to get the 5 but if this would be empty assign 0 as the default value, for instance if the measurement is "lb. 8oz." I want pounds to get the value of 0.

In the following example, I do get 5 but it crashes if I change measurement from "5lb. 8oz." to "lb. 8oz."

let measurement = "5lb. 8oz."

let arrayOfStrings:[String] = measurement.components(separatedBy: "l")
print("Array of Strings: \(arrayOfStrings)") //Output: Array of Strings: ["5", "b. 8oz."]

let pounds = Double(arrayOfStrings[0] ?? "0") 
print("Pounds \(pounds!)") //Output: Pounds 5.0

Error: When changing measurement to "lb. 8oz."

Fatal error: Unexpectedly found nil while unwrapping an Optional value

FYI - I'm looking for a single line solution, I know how to do it using if let or guard.

fs_tigre
  • 10,650
  • 13
  • 73
  • 146
  • If you are not opposed to using Foundation then a simple `let pounds = (measurement as NSString).doubleValue` does the trick. – Martin R Oct 25 '19 at 12:30

2 Answers2

1

You can unwrap the access of the array and the conversion to Double

let pounds = Double(arrayOfStrings.first ?? "0") ?? 0.0
Joakim Danielson
  • 43,251
  • 5
  • 22
  • 52
  • I get error `let pounds = Double(arrayOfStrings.first ?? "0") ?? 0.0` Error: ` error: cannot force unwrap valueof non-optional type 'Double'` – fs_tigre Oct 25 '19 at 12:31
  • 1
    @fs_tigre Are you sure that error refers to that line? `pounds` is no longer optional with this solution so you can't unwrap it any more – Joakim Danielson Oct 25 '19 at 12:33
  • Oops, no it was referring to `print("Pounds \(pounds!)")`, removed `!` and it worked. – fs_tigre Oct 25 '19 at 12:35
  • Is this what is referred to `optional chaining`? – fs_tigre Oct 25 '19 at 12:38
  • 1
    @fs_tigre No that is when you have an optional variable/property that you ar calling a property or method on. `var array: [String]?; array?.count` – Joakim Danielson Oct 25 '19 at 12:52
  • 1
    @fs_tigre, no this is not *optional chaining*. Optional chaining is when you place a single `?` after an optional and then proceed to access a member or call a function on it. See [this answer](https://stackoverflow.com/a/27734933/1630618) for examples of *optional chaining*. – vacawama Oct 25 '19 at 12:54
  • @JoakimDanielson - Quick question. Why is that your solution only works if I use `.first ?? "0"` but it doesn't work if I change it to `[0] ?? "0"`? What if I wanted to extract the second item from the array `[1] ?? "0"`? – fs_tigre Oct 27 '19 at 18:30
  • 1
    @fs_tigre If the array is empty .first will return nil but [0] will crash. If you want to access the array like that, [0], [1] etc, you better check the length of the array first. Also since [0] is not optional it is pointless to do `[0] ?? "0"` because the `?? "0"` part will never be executed – Joakim Danielson Oct 27 '19 at 19:08
1
let pounds = Double(arrayOfStrings[0]) ?? 0.0
print("Pounds \(pounds)")

Works for me.

Khushneet
  • 854
  • 9
  • 10