0

I have the following code in a playground:

// Create an empty array of optional integers
var someOptionalInts = [Int?]()

// Create a function squaredSums3 with one argument, i.e. an Array of optional Ints
func squaredSums3(_ someOptionalInts: Int?...)->Int {
    // Create a variable to store the result
    var result = 0

    // Get both the index and the value (at the index) by enumerating through each element in the someOptionalInts array
    for (index, element) in someOptionalInts.enumerated() {
        // If the index of the array modulo 2 is not equal to 0, then square the element at that index and add to result
        if index % 2 != 0 {
            result += element * element
        }
    }

    // Return the result
    return result
}

// Test the code
squaredSums3(1,2,3,nil)

The line result += element * element is giving the following error "Value of optional type 'Int?' not unwrapped; did you mean to use '!' or '?'?" I do not want to use '!' and I have to test for the nil case. I am not sure where (or even how to be honest) to unwrap the optional. Suggestions?

  • Do a `if let`: `if let unwrappedElement = element { if index %2... {} }`? That's basic unwrapping. Or you can unwrapped already `someOptionalInts` instead of doing `someOptionalInts`, do `let unwrappedSomeInts = someOptionalInts.flatMap{ $0 }` and use it for the loop. – Larme Sep 04 '18 at 13:18
  • `result = (element ?? 0) * (element ?? 0)` – Claus Jørgensen Sep 04 '18 at 13:20

4 Answers4

2

All you have to do is unwrap the optional:

if let element = element, index % 2 != 0 {
    result += element * element
}

This will ignore the nil values.

The advantage of this over any sort of mapping is that you don't have to traverse the array an extra time.

jancakes
  • 456
  • 4
  • 10
  • Okay, thank you! I am new to optionals and they are just a little bit confusing. I'm sure I'll get use to them as I use them more. Thank you! –  Sep 04 '18 at 14:36
  • No problem at all. They definitely take some getting used to. – jancakes Sep 04 '18 at 14:38
  • @MatthewSpire but you said you couldn't just ignore the ones that are nil! Here you also do that. – LinusGeffarth Sep 04 '18 at 15:08
  • @LinusGeffarth I think he meant he couldn't just filter them out because that would throw off the indices. A compact map would turn [1, nil, 2, 3] into [1, 2, 3], and then his mod operation on the index would be wrong. – jancakes Sep 04 '18 at 15:28
  • Ah, probably, yeah. – LinusGeffarth Sep 04 '18 at 15:29
  • Yes, I think @jancakes understood what I meant. I appreciate both of your helps. Thank you! –  Sep 04 '18 at 17:54
1

If you wanted to leave out the nil values from the array, you could compact map it:

for (index, element) in (someOptionalInts.compactMap { $0 }).enumerated() {

Then, element would not be optional anymore.


If you instead wanted to treat all nil values as 0, then you could do:

if index % 2 != 0 {
    result += (element ?? 0) * (element ?? 0)
}
LinusGeffarth
  • 27,197
  • 29
  • 120
  • 174
  • I can't leave out the nil values from the array. The squaredSums3(1,2,3,nil) should return 4, which means that it's accounting for the fact that the nil is in the array and is basically just ignoring it. –  Sep 04 '18 at 13:36
  • @MatthewSpire So what's your goal? How do you want to deal with the nil value? Should it be treated like a `0`? – LinusGeffarth Sep 04 '18 at 13:40
0

The error appears because you have to specify what to do in case element is nil

if index % 2 != 0 {
    if let element = element {
        result += element * element
    }
    else {
        // do whatever you want
    }
}
zheck
  • 298
  • 3
  • 11
0

Here's how I would write it:

for (index, element) in someOptionalInts.enumerated() {
    guard let element = element, index % 2 == 0 else { continue }
    result += element * element
}
// result == 10

The guard statement means that I'm only interested when element is not nil and its index is even.

Code Different
  • 90,614
  • 16
  • 144
  • 163