函数数组<Optional<T>> -> 可选<Array<T>>
Function Array<Optional<T>> -> Optional<Array<T>>
这是我正在尝试做的事情:
extension Array<Optional<T>> {
func unwrap() -> Optional<Array<T>> {
let a = self.flatMap() { a in
switch a {
case Optional.Some(let x): return [x]
case Optional.None: return []
}
}
if a.count == self.count {
return Optional.Some(a)
} else {
return Optional.None
}
}
}
但是,它没有编译错误 Use of undeclared type T
。
以下是我想如何使用它:
let a = [Optional.Some(2), Optional.Some(3), Optional.Some(4)]
let b = [Optional.Some(1), Optional.None]
a.unwrap() // Optional[2, 3, 4]
b.unwrap() // nil
我该如何解决这个问题?或者swift没有这种可能?
试试这个:
protocol OptionalType {
typealias W
var optional: W? { get }
}
extension Optional: OptionalType {
typealias W = Wrapped
var optional: W? { return self }
}
extension Array where Element: OptionalType {
func unwrap() -> [Element.W]? {
return reduce(Optional<[Element.W]>([])) { acc, e in
acc.flatMap { a in e.optional.map { a + [[=10=]] } }
}
}
}
然后,
let a: [Int?] = [1, 2, 3]
let b: [Int?] = [1, nil, 3]
a.unwrap() // ==> [1, 2, 3]
b.unwrap() // ==> nil
findall 的解决方案有效,尽管我认为在这种情况下避免泛型更具可读性:
func unwrap<Element>(optionalArray : [Element?]) -> [Element]? {
let unwrappedArray = optionalArray.flatMap { (a) -> [Element] in
switch a {
case Optional.Some(let x): return [x]
case Optional.None: return []
}
}
return unwrappedArray.count == optionalArray.count ? Optional.Some(unwrappedArray) : Optional.None
}
用法:
let a = [Optional.Some(2), Optional.Some(3), Optional.Some(4)]
let b = [Optional.Some(1), Optional.None]
// Both are [Int]?
let unwrappedA = unwrap(a) // [2, 3, 4]
let unwrappedB = unwrap(b) // nil
另请参阅:How to determine if a generic is an optional in Swift?
Swift 4
受@findall 解决方案的启发,这适用于 Swift 4:
protocol OptionalType {
associatedtype Wrapped
var optional: Wrapped? { get }
}
extension Optional: OptionalType {
var optional: Wrapped? { return self }
}
extension Sequence where Iterator.Element: OptionalType {
func removeNils() -> [Iterator.Element.Wrapped] {
return self.flatMap { [=10=].optional }
}
}
测试:
class UtilitiesTests: XCTestCase {
func testRemoveNils() {
let optionalString: String? = nil
let strings: [String?] = ["Foo", optionalString, "Bar", optionalString, "Baz"]
XCTAssert(strings.count == 5)
XCTAssert(strings.removeNils().count == 3)
let integers: [Int?] = [2, nil, 4, nil, nil, 5]
XCTAssert(integers.count == 6)
XCTAssert(integers.removeNils().count == 3)
}
}
这是我正在尝试做的事情:
extension Array<Optional<T>> {
func unwrap() -> Optional<Array<T>> {
let a = self.flatMap() { a in
switch a {
case Optional.Some(let x): return [x]
case Optional.None: return []
}
}
if a.count == self.count {
return Optional.Some(a)
} else {
return Optional.None
}
}
}
但是,它没有编译错误 Use of undeclared type T
。
以下是我想如何使用它:
let a = [Optional.Some(2), Optional.Some(3), Optional.Some(4)]
let b = [Optional.Some(1), Optional.None]
a.unwrap() // Optional[2, 3, 4]
b.unwrap() // nil
我该如何解决这个问题?或者swift没有这种可能?
试试这个:
protocol OptionalType {
typealias W
var optional: W? { get }
}
extension Optional: OptionalType {
typealias W = Wrapped
var optional: W? { return self }
}
extension Array where Element: OptionalType {
func unwrap() -> [Element.W]? {
return reduce(Optional<[Element.W]>([])) { acc, e in
acc.flatMap { a in e.optional.map { a + [[=10=]] } }
}
}
}
然后,
let a: [Int?] = [1, 2, 3]
let b: [Int?] = [1, nil, 3]
a.unwrap() // ==> [1, 2, 3]
b.unwrap() // ==> nil
findall 的解决方案有效,尽管我认为在这种情况下避免泛型更具可读性:
func unwrap<Element>(optionalArray : [Element?]) -> [Element]? {
let unwrappedArray = optionalArray.flatMap { (a) -> [Element] in
switch a {
case Optional.Some(let x): return [x]
case Optional.None: return []
}
}
return unwrappedArray.count == optionalArray.count ? Optional.Some(unwrappedArray) : Optional.None
}
用法:
let a = [Optional.Some(2), Optional.Some(3), Optional.Some(4)]
let b = [Optional.Some(1), Optional.None]
// Both are [Int]?
let unwrappedA = unwrap(a) // [2, 3, 4]
let unwrappedB = unwrap(b) // nil
另请参阅:How to determine if a generic is an optional in Swift?
Swift 4
受@findall 解决方案的启发,这适用于 Swift 4:
protocol OptionalType {
associatedtype Wrapped
var optional: Wrapped? { get }
}
extension Optional: OptionalType {
var optional: Wrapped? { return self }
}
extension Sequence where Iterator.Element: OptionalType {
func removeNils() -> [Iterator.Element.Wrapped] {
return self.flatMap { [=10=].optional }
}
}
测试:
class UtilitiesTests: XCTestCase {
func testRemoveNils() {
let optionalString: String? = nil
let strings: [String?] = ["Foo", optionalString, "Bar", optionalString, "Baz"]
XCTAssert(strings.count == 5)
XCTAssert(strings.removeNils().count == 3)
let integers: [Int?] = [2, nil, 4, nil, nil, 5]
XCTAssert(integers.count == 6)
XCTAssert(integers.removeNils().count == 3)
}
}