How can I remove all nil elements in a Swift array?

IosSwift

Ios Problem Overview


Basic way doesn't work.

for index in 0 ..< list.count {
    if list[index] == nil {
        list.removeAtIndex(index) //this will cause array index out of range
    }
}

Ios Solutions


Solution 1 - Ios

The problem with your code is that 0 ..< list.count is executed once at the beginning of the loop, when list still has all of its elements. Each time you remove one element, list.count is decremented, but the iteration range is not modified. You end up reading too far.

In Swift 4.1 and above, you can use compactMap to discard the nil elements of a sequence. compactMap returns an array of non-optional values.

let list: [Foo?] = ...
let nonNilElements = list.compactMap { $0 }

If you still want an array of optionals, you can use filter to remove nil elements:

list = list.filter { $0 != nil }

Solution 2 - Ios

In Swift 2.0 you can use flatMap:

list.flatMap { $0 }

Solution 3 - Ios

Now in swift 4.2 you can use

list.compactMap{ $0 }

list.flatMap{ $0 } is already deprecated.

Solution 4 - Ios

A much elegant solution would be to use compacted() defined in the Algorithms package made by Apple itself.

import Algorithms

let array = [10, nil, 20, nil, 30]
print(array.compacted()) // prints [10, 20, 30]
Benefits
  1. Concise
  2. Filters out nil items lazily

More info https://github.com/apple/swift-algorithms/blob/main/Guides/Compacted.md

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionTIMEXView Question on Stackoverflow
Solution 1 - IoszneakView Answer on Stackoverflow
Solution 2 - IosMarcel MolinaView Answer on Stackoverflow
Solution 3 - IoskalafunView Answer on Stackoverflow
Solution 4 - IosKaunteyaView Answer on Stackoverflow