swift:优雅的映射方式可选数组



我正在寻找一种将Optional映射到Array的优雅方法。我的意思是:

  • 如果Optional.none,则返回空的Array<Wrapped>
  • 如果Optional.some,则返回单个元素Array<Wrapped>

现在可以像这样完成

let seq = value.map { [$0] } ?? []

不幸的是,当你想内联使用它时,它会变得非常丑陋和难以辨认。

有没有更好的方法可以在不编写extension的情况下实现这一点?

把你的可选项放在一个数组中,然后用标识函数compactMap这个数组怎么样?

[yourOptional].compactMap { $0 }

正如Martin R所建议的那样,您可以使用CollectionOfOne来节省一次性数组的创建,代价是多写几个字符:

CollectionOfOne(yourOptional).compactMap { $0 }

有没有更好的方法可以在不编写扩展的情况下实现这一点?

否。您正在寻找的方法仍然没有进入Swift标准库。

public extension Optional {
/// Create a single-element array literal, or an empty one.
/// - Returns: `[self!]` if `.some`; `[]` if `nil`.
/// - Note: This cannot be generalized to all types,
/// as Swift doesn't employ  universal non-optional defaults.
func compacted<ExpressibleByArrayLiteral: Swift.ExpressibleByArrayLiteral>() -> ExpressibleByArrayLiteral
where ExpressibleByArrayLiteral.ArrayLiteralElement == Wrapped {
.init(compacting: self)
}
}
// MARK: - ExpressibleByArrayLiteral
public extension ExpressibleByArrayLiteral {
/// Create a single-element array literal, or an empty one.
/// - Returns: `[optional!]` if `.some`; `[]` if `nil`.
/// - Note: This cannot be generalized to all types,
/// as Swift doesn't employ  universal non-optional defaults.
init(compacting optional: ArrayLiteralElement?) {
self = optional.map { [$0] } ?? []
}
}
XCTAssertEqual(
["💿🗺"],
("💿🗺" as Optional).compacted()
)
XCTAssertEqual(
Set(),
Int?.none.compacted()
)

C#是一种语言的例子;通用非可选默认值">


NSPointerArray具有无自变量compact,这是一个类似的概念,也是标准库中确实存在的compactMap前半部分的灵感来源。它现在以compacted的形式提供。

最新更新