2016-07-18 83 views
2

我一直在試圖從字符串數組中提取非零值。如下所示。但是,我的資深人士也希望能夠從其他類型中提取非零值如何使集合類型約束中的泛型?

我讀,仿製藥能幫助我處理不同的類型。我怎樣才能使用泛型,以便我可以像使用擴展一樣使用其他類型? (如果陣列是即[字符串?]它必須返回[字符串],返回[INT]如果[詮釋?]

getNonNil必須返回的特定類型的所提取的非零值

由於我必須做進一步的計算。

我已經試過低於:

import Foundation 
// Extended the collection-type so that collectiontype is constrained to having element with optional strings 
extension CollectionType where Self.Generator.Element == Optional<String>{ 
    func getNonNil() -> [String] { 
     // filter out all nil elements and forcefully unwrap them using map 
     return self.filter({$0 != nil}).map({$0!}) 
    } 
} 

// Usage 
let x: [String?] = ["Er", "Err", nil, "errr"] 

x.getNonNil().forEach { (str) in 
    print(str) 
} 

回答

2

對於getNonNil,你可以簡單地使用

x.flatMap { $0 } 
// returns ["Er", "Err", "errr"] which is [String] 

對於原來的問題,通常你可以引入協議擇類型(經由muukii/OptionalProtocol包EG):

protocol OptionalProtocol { 
    associatedtype Wrapped 
    var value: Wrapped? { get } 
} 

extension Optional: OptionalProtocol { 
    public var value: Wrapped? { return self } 
} 

extension CollectionType where Self.Generator.Element: OptionalProtocol { 
    func getNonNil() -> [Self.Generator.Element.Wrapped] { 
     ... 
    } 
} 
+0

flatmap工作。但在第二種解決方案中,我該如何使用它?你能向我展示一個例子嗎?因爲,當我嘗試時,我得到了「致命錯誤:意外地發現零,同時解開一個可選值」或其他錯誤。 – Dari

+0

@Dari您可能想在'getNonNil'方法中執行'return flatMap {$ 0.value}'。 – Hamish

2

有通過擴展實現這一點,因爲你不能引入新的通用類型爲擴展名(儘管這是part of the Swift Generics Manifesto - 所以很可能是有可能在斯威夫特的未來版本)的沒有簡單的方法。

由於@kennytm says,最簡單的辦法就是使用flatMap,過濾掉nil

x.flatMap{$0}.forEach { (str) in 
    print(str) 
} 

但是,如果你仍然要使用這個擴展,你可以使用協議的解決方法,以允許您約束擴展到任何任選的元素類型(SWIFT 3):

protocol _OptionalProtocol { 
    associatedtype Wrapped 
    func _asOptional() -> Wrapped? 
} 

extension Optional : _OptionalProtocol { 
    func _asOptional() -> Wrapped? {return self} 
} 

extension Collection where Self.Iterator.Element : _OptionalProtocol { 
    func getNonNil() -> [Iterator.Element.Wrapped] { 
     return flatMap{$0._asOptional()} 
    } 
} 

... 

let x : [String?] = ["Er", "Err", nil, "errr"] 

x.getNonNil().forEach { (str) in 
    print(str) 
} 

(在夫特3,CollectionType已更名爲Collection,並Generator現在Iterator

雖然flatMap在這種情況下,幾乎可以肯定是首選,我才真正加入該完成的緣故。

0

最簡單的方法是使用flatMapkennytm建議,但如果你絕對想知道如何使用泛型創建這樣一種方法,一種方法是創建,是以集合作爲參數在全球的方法:

public func getNonNil<T, C: CollectionType where C.Generator.Element == Optional<T>>(collection: C) -> [T] { 
    return collection.filter({$0 != nil}).map({$0!}) 
} 

let x: [String?] = ["Er", "Err", nil, "errr"] 

print(getNonNil(x)) // returns ["Er", "Err", "errr"]