【问题标题】:How to loop through an optional collection如何遍历可选集合
【发布时间】:2021-07-26 12:35:13
【问题描述】:

在循环之前直接解开可选集合的 Swifty 方法是什么? 考虑以下几点:

let elements: [Element]?
for element in elements { ... }

其中elements 可能包含值。编译器产生错误:For-in loop requires '[Element]?' to conform to 'Sequence'; did you mean to unwrap optional?,与forEach类似。

使用where-关键字告诉编译器我只想在elements中有这样的值时进行迭代

for element in elements where elements != nil { ... }

不起作用。我基本上是在寻找一种方法来解开集合,在循环之前我不必写冗长的guard letif let

我不希望使用返回未包装 self 的属性来扩展 Sequence,我只是认为它不是很优雅(包括强制展开)。

【问题讨论】:

  • for element in elements ?? [] {} ?
  • guardif let 有什么这么冗长的?这是安全地解开可选项并遵循常用模式的常规方法,这本身就是一种优势。
  • 使用一些样式指南,您需要在任何要解包值的地方编写 3 行新代码,这只是 冗长的 imo。请在 Swift 社区论坛上查看thread,了解更多关于此的意见
  • 将你的集合声明为常量是没有意义的

标签: swift collections optional


【解决方案1】:

您有几个选择。您可以在for ... in 循环中提供一个空数组作为elements 的默认值:

let elements: [Element]?

for element in elements ?? [] {

}

或者您可以使用forEachelements 上的可选链接

elements?.forEach { element in

}

请记住,可选集合在 Swift 中是一种反模式。您可以使用空集合来表示缺少值,因此将集合包装在可选项中不会提供任何额外的值,同时会使接口复杂化。

【讨论】:

  • 我不觉得第一个选项在可读性方面非常好,不过我喜欢第二个选项。我想我一直坚持使用where,所以我忘记了可选链接,呃......
  • SwiftLint 甚至为此设置了 rule,很好
  • 将其声明为常量没有意义
【解决方案2】:

您的元素不是可选的,但数组是可选的。在您的情况下,只需打开数组:

let elements: [Element]?
for element in elements ?? [] {
    // do stuff
}

但如果你的元素是可选的,你可以使用 compactMap:

let elements: [Element?] // elements are optional instead of array
for element in elements.compactMap { $0 } {
    // do stuff
}

【讨论】:

  • 如果元素为 nil 那么你可以像这样使用它for case let element in elements {
  • 附注,compactMap():您正在迭代数组两次...所以它可能未优化...
猜你喜欢
  • 2014-07-21
  • 2014-04-11
  • 2018-11-17
  • 1970-01-01
  • 2019-12-04
  • 2021-03-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多