Reputation:
I am looking for an elegant way to map an Optional
to an Array
. What I mean by that is the following:
Optional
is .none
, return an empty Array<Wrapped>
Optional
is .some
, return a single element Array<Wrapped>
Now this can be done like this
let seq = value.map { [$0] } ?? []
Unfortunately this gets quite ugly and illegible when you want to use it inline.
Is there a better method to accomplish this, without writing a extension
?
Upvotes: 3
Views: 850
Reputation:
Is there a better method to accomplish this, without writing a extension?
No. The method you're looking for still hasn't made its way into the Swift Standard Library.
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# is an example of a language with "universal non-optional defaults".
NSPointerArray has the argument-less compact
, which is a similar concept, and the inspiration for the first half of the compactMap
that does exist in the standard library. It's now available as compacted
.
Upvotes: 1
Reputation: 272725
How about putting your optional in an array, and compactMap
that array with the identity function?
[yourOptional].compactMap { $0 }
As Martin R suggested, you can use CollectionOfOne
to save the creation of a throwaway array, at the cost of writing a few more characters:
CollectionOfOne(yourOptional).compactMap { $0 }
Upvotes: 2