如何在Swift数组中删除所有的nil元素?

89

基本方法不起作用。

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

可能是重复的问题:Swift:快捷解包可选数组 - Senseful
4个回答

191
您的代码问题在于,在循环开始时执行0 ..< list.count,此时list仍具有所有元素。每次删除一个元素后,list.count会递减,但迭代范围不会修改。你最终会读取过多。

在Swift 4.1及以上版本中,您可以使用compactMap来丢弃序列中的nil元素。compactMap返回一个非可选值数组。

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

如果您仍然想要一个包含可选项的数组,可以使用 filter 函数移除其中的 nil 元素:

答案:如果您仍需要一个可选项数组,可以使用过滤器(filter)来删除nil元素:
list = list.filter { $0 != nil }

76

在Swift 2.0中,您可以使用flatMap:

list.flatMap { $0 }

这也有一个额外的好处,即不需要列表中的对象是可比较的。 - Tim
1
既然我们拥有了它,这是一个更好的解决方案。 - zneak
9
依靠 flatMap { $0 } 去除 nils 可能会导致错误。相反,使用类似于 removeNils() 的扩展方法来解决这个问题,具体实现可以参考这里:https://dev59.com/CV4c5IYBdhLWcg3wM3-R#38548106。 - Senseful

48

现在在swift 4.2中,您可以使用

list.compactMap{ $0 }

list.flatMap{ $0 }已经过时。


flatMap并没有被弃用,而是现在有了不同的用例。 - Sentry.co

2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接