Comment faire des generics dans une contrainte de type collection?

J'ai essayé d'extraire des valeurs non nulles du tableau Ssortingng. Comme ci-dessous. Mais mon aîné veut aussi pouvoir extraire des valeurs non nulles d'autres types.

J'ai lu, les generics pourraient m'aider à gérer différents types. Comment puis-je utiliser des generics pour que je puisse utiliser l'extension suivante pour travailler avec d'autres types?

getNonNil doit renvoyer les valeurs non nulles extraites du type spécifique (ie si array est [Ssortingng?] il doit returnner [Ssortingng], returnne [Int] if [Int?] )

Parce que je dois faire d'autres calculs.

Ce que j'ai essayé est ci-dessous:

 import Foundation // Extended the collection-type so that collectiontype is constrained to having element with optional ssortingngs extension CollectionType where Self.Generator.Element == Optional<Ssortingng>{ func getNonNil() -> [Ssortingng] { // filter out all nil elements and forcefully unwrap them using map return self.filter({$0 != nil}).map({$0!}) } } // Usage let x: [Ssortingng?] = ["Er", "Err", nil, "errr"] x.getNonNil().forEach { (str) in print(str) } 

Il n'y a pas de moyen facile d'y parvenir grâce à une extension, car vous ne pouvez pas introduire de nouveaux types generics dans les extensions (bien que cela fasse partie du Manifeste Swift Generics – peut-être dans une future version de Swift).

Comme le dit @kennytm , la solution la plus simple consiste simplement à utiliser flatMap , qui filter nil :

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

Si toutefois vous voulez toujours cela comme une extension, vous pouvez utiliser une solution de contournement de protocole afin de vous permettre de contraindre l'extension à tout type d'élément optionnel (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 : [Ssortingng?] = ["Er", "Err", nil, "errr"] x.getNonNil().forEach { (str) in print(str) } 

(Dans Swift 3, CollectionType a été renommé en Collection , et Generator est maintenant Iterator )

Bien que flatMap soit presque certainement préféré dans cette situation, je ne fais que l'append pour l'amour de l'achèvement.

Pour getNonNil vous pouvez simplement utiliser

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

Pour la question d'origine, vous pouvez typiquement introduire un protocole au type optionnel (par exemple via le packageage muukii / OptionalProtocol ):

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

L'approche la plus simple consiste à utiliser flatMap comme suggéré par kennytm , mais si vous voulez absolument savoir comment créer une telle méthode en utilisant des generics, une approche consisterait à créer une méthode globale qui prend en count la collection en tant que paramètre:

 public func getNonNil<T, C: CollectionType where C.Generator.Element == Optional<T>>(collection: C) -> [T] { return collection.filter({$0 != nil}).map({$0!}) } let x: [Ssortingng?] = ["Er", "Err", nil, "errr"] print(getNonNil(x)) // returns ["Er", "Err", "errr"]