我正在寻找一种将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
的形式提供。