21

Let's say I have a Swift object called Animal. I have an array of Animal objects, some of which could be nil.

Currently I'm doing this:

arrayOfAnimal.filter({$0 != nil}) as! [Animal]

This feels rather hacky because of the force unwrapping. Wondering if there's a better way to filter out nils.

7ball
  • 2,183
  • 4
  • 26
  • 61

2 Answers2

54

flatMap() does the job:

let filtered = arrayOfAnimal.flatMap { $0 }

The closure (which is the identity here) is applied to all elements, and an array with the non-nil results is returned. The return type is [Animal] and no forced cast is needed.

Simple example:

let array: [Int?] = [1, nil, 2, nil, 3]
let filtered = array.flatMap { $0 }

print(filtered)            // [1, 2, 3]
print(type(of: filtered))  // Array<Int>

For Swift 4.1 and later, replace flatMap by compactMap.

Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
16

Your code works, but there is a better way. Use the compactMap function.

struct Animal {}

let arrayOfAnimal: [Animal?] = [nil, Animal(), Animal(), nil]
let newArray: [Animal] = arrayOfAnimal.compactMap { $0 }
koen
  • 5,383
  • 7
  • 50
  • 89
picciano
  • 22,341
  • 9
  • 69
  • 82