Function Array> -> Optional>

前端 未结 3 1706
半阙折子戏
半阙折子戏 2021-01-06 09:12

Here is what I\'m trying to do:

extension Array> {   
  func unwrap() -> Optional> {
    let a = self.flatMap         


        
相关标签:
3条回答
  • 2021-01-06 09:51

    findall's solution works, although I think it's more readable to just avoid generics for this case:

    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
    }
    

    Usage:

    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
    

    See also: How to determine if a generic is an optional in Swift?

    0 讨论(0)
  • 2021-01-06 10:00

    Swift 4

    Inspired by the solution by @findall, this works with 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 { $0.optional }
        }
    }
    

    Test:

    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)
        }
    }
    
    0 讨论(0)
  • 2021-01-06 10:11

    Try this:

    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] } }
            }
        } 
    }
    

    And then,

    let a: [Int?] = [1,   2, 3]
    let b: [Int?] = [1, nil, 3]
    
    a.unwrap() // ==> [1, 2, 3]
    b.unwrap() // ==> nil
    
    0 讨论(0)
提交回复
热议问题