0

how to get a first item in empty list to use guard let or if let.

For example, I have an empty list and I would like to get gracefully first item in list like here, but it looks like:

var empty_array: [Int] = []
guard let first = empty[0] as? Int else{
    // do something
}
// after operation first should be nil

And my code crashes because first item missed in list and I would like to get result of first item that will be nil. How to do this?

UPDATED: to get first item needs use

guard let first = empty.first as? Int else{
    // do something
}

But what about second or third item?

user2930077
  • 135
  • 2
  • 9

3 Answers3

1

Use empty.first, which returns a T?.

guard let first = empty.first else {
    // do something
}

Note that the body of a guard statement must exit the parent scope. It sounds like your comments have it backwards (first is nil in the guard scope, not after it).

zneak
  • 134,922
  • 42
  • 253
  • 328
  • Yes, you are right for first item, but if I would like to get another index(for example two or three), or perhaps I would like to check another condition of list, I mean exists some way to check condition before to init a first variable? – user2930077 Feb 14 '18 at 09:10
  • 1
    @user2930077: If you are looking for a "safe subscript" then have a look at https://stackoverflow.com/a/30593673/1187415. – Martin R Feb 14 '18 at 09:17
  • @user2930077, you can check if an index is valid for an array using `array.indices ~= index`, and you can easily use it to create a subscript in an extension. – zneak Feb 14 '18 at 16:55
1

You could either

var empty: [Int] = []
guard let first = empty.first else {
// cast did fail - do any stuff to escape this func or whatever you would like to do
}
// access first here --> first is not nil 

or

var empty: [Int] = []
if let first = empty.first {
// access first here --> first is not nil 
} else {
// cast did fail - do stuff 
}
Teetz
  • 3,475
  • 3
  • 21
  • 34
0

The reason it crashes is because getting an element from an array using a subscript does not return an optional. If no element exists at the index it simply crashes with index out of bounds. This is in contrast to dictionaries where subscript access returns an optional. The rationale behind this design decision is that, for arrays, unwrapping the optional every time would be a right pain, especially as all you have to do is test the index is in 0 ..< array.count.

Your guard statement tries to access an array element that does not exist, so it crashes. Also, your guard statement is the wrong way around. The block after the else is what is executed in the exceptional condition.

So, if you use empty_array.first which does return an optional, you should do this:

guard let first = empty_array.first else { return /* bail out of the function */ }

doSomething(with: first) // first is unwrapped here.

Or use if

if let first = empty_array.first
{
    doSomething(with: first) // first is unwrapped here.
}

Or you can test the index to make sure it is in range. Has the advantage of working with any index, not just zero

let index = // Some integer

guard index >= 0 && index < empty_array.count else { return }

doSomething(with: empty_array[index])

Or

guard (0 ..< empty_array.count).contains(index) else { return }
JeremyP
  • 84,577
  • 15
  • 123
  • 161