首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >函数Array<Optional<T>> -> Optional<Array<T>>

函数Array<Optional<T>> -> Optional<Array<T>>
EN

Stack Overflow用户
提问于 2015-10-15 02:15:57
回答 3查看 1.1K关注 0票数 4

以下是我要做的事:

代码语言:javascript
复制
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进行编译。下面是我想要使用的方法:

代码语言:javascript
复制
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

我该怎么处理这件事?或者在斯威夫特没有这样的可能性?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-10-15 03:15:31

试试这个:

代码语言:javascript
复制
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 + [$0] } }
        }
    } 
}

然后,

代码语言:javascript
复制
let a: [Int?] = [1,   2, 3]
let b: [Int?] = [1, nil, 3]

a.unwrap() // ==> [1, 2, 3]
b.unwrap() // ==> nil
票数 9
EN

Stack Overflow用户

发布于 2017-06-18 10:33:00

Swift 4

在@findall的解决方案的启发下,这个方法适用于Swift 4:

代码语言:javascript
复制
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 { $0.optional }
    }
}

测试:

代码语言:javascript
复制
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)
    }
}
票数 5
EN

Stack Overflow用户

发布于 2015-10-15 03:23:54

findall的解决方案很有效,不过我认为只需在这种情况下避免泛型是更容易理解的:

代码语言:javascript
复制
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
}

用法:

代码语言:javascript
复制
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?

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33138712

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档