extension Array {
func removeObject<T where T : Equatable>(object: T) {
var index = find(self, object)
self.removeAtIndex(index)
}
}
Cependant, j'obtiens une erreur sur var index = find(self, object)
«T» n'est pas convertible en «T»
J'ai aussi essayé avec cette signature de méthode: func removeObject(object: AnyObject)
cependant, j'obtiens la même erreur:
'AnyObject' n'est pas convertible en 'T'
Quelle est la bonne façon de procéder?
T where
de votre déclaration de méthode. Tellement justefunc removeObject<T: Equatable>
. Cette question est liée: stackoverflow.com/questions/24091046/…Réponses:
À partir de Swift 2 , cela peut être réalisé avec une méthode d'extension de protocole .
removeObject()
se définit comme une méthode sur tous les types conforme àRangeReplaceableCollectionType
(en particulier surArray
) si les éléments de la collection sontEquatable
:Exemple:
Mise à jour pour Swift 2 / Xcode 7 beta 2: Comme Airspeed Velocity l'a remarqué dans les commentaires, il est désormais possible d'écrire une méthode sur un type générique plus restrictif sur le modèle, donc la méthode pourrait désormais être définie comme une extension de
Array
:L'extension de protocole a toujours l'avantage d'être applicable à un plus grand ensemble de types.
Mise à jour pour Swift 3:
la source
remove(object: Element)
en afin de se conformer aux directives de conception de l'API Swift et d'éviter la verbosité. J'ai soumis une modification reflétant cela.Vous ne pouvez pas écrire une méthode sur un type générique qui est plus restrictif sur le modèle.
REMARQUE : à partir de Swift 2.0, vous pouvez maintenant écrire des méthodes qui sont plus restrictives sur le modèle. Si vous avez mis à niveau votre code vers 2.0, consultez les autres réponses ci-dessous pour de nouvelles options pour implémenter cela à l'aide d'extensions.
La raison pour laquelle vous obtenez l'erreur
'T' is not convertible to 'T'
est que vous définissez en fait un nouveau T dans votre méthode qui n'est pas du tout lié au T. d'origine. Si vous souhaitez utiliser T dans votre méthode, vous pouvez le faire sans le spécifier dans votre méthode.La raison pour laquelle vous obtenez la deuxième erreur
'AnyObject' is not convertible to 'T'
est que toutes les valeurs possibles pour T ne sont pas toutes des classes. Pour qu'une instance soit convertie en AnyObject, il doit s'agir d'une classe (ce ne peut pas être une structure, une énumération, etc.).Votre meilleur pari est d'en faire une fonction qui accepte le tableau comme argument:
Ou au lieu de modifier le tableau d'origine, vous pouvez rendre votre méthode plus sûre pour les threads et réutilisable en renvoyant une copie:
Comme alternative que je ne recommande pas, vous pouvez faire échouer votre méthode en silence si le type stocké dans le tableau ne peut pas être converti en modèle de méthodes (qui peut être égalisé). (Pour plus de clarté, j'utilise U au lieu de T pour le modèle de la méthode):
Edit Pour surmonter l'échec silencieux, vous pouvez renvoyer le succès sous forme de valeur booléenne:
la source
find
méthode?Equatable
protocole. UIView le fait oui, il fonctionnera avec UIViewsenumerate(self)
doit réparer àself.enumerate()
brièvement et de manière concise:
la source
inout
. Même avec leinout
intact, on pourrait utiliserarray = array.filter() { $0 != object }
, je pense.Après avoir lu tout ce qui précède, à mon avis, la meilleure réponse est:
Échantillon:
Extension de tableau Swift 2 (xcode 7b4):
Échantillon:
Mise à jour Swift 3.1
J'y suis revenu maintenant que Swift 3.1 est sorti. Vous trouverez ci-dessous une extension qui fournit des variantes exhaustives, rapides, mutantes et créatrices.
Échantillons:
la source
filter
fonction gère déjà cette fonctionnalité pour vous. Cela semble dupliquer la fonctionnalité. Mais une bonne réponse tout de même:]Avec les extensions de protocole, vous pouvez le faire,
Même fonctionnalité pour les cours,
Swift 2
Swift 3
Mais si une classe implémente Equatable, cela devient ambigu et le compilateur renvoie une erreur.
la source
Binary operator '===' cannot be applied to two elements of type '_' and 'Element'
Avec l'utilisation d'extensions de protocole dans Swift 2.0
la source
qu'en est-il du filtrage? ce qui suit fonctionne assez bien même avec [AnyObject].
la source
Il existe une autre possibilité de supprimer un élément d'un tableau sans avoir une utilisation non sécurisée possible, car le type générique de l'objet à supprimer ne peut pas être le même que le type du tableau. L'utilisation d'options n'est pas non plus la solution idéale car elles sont très lentes. Vous pouvez donc utiliser une fermeture comme elle est déjà utilisée lors du tri d'un tableau par exemple.
Lorsque vous étendez la
Array
classe avec cette fonction, vous pouvez supprimer des éléments en procédant comme suit:Cependant, vous pouvez même supprimer un élément uniquement s'il a la même adresse mémoire (uniquement pour les classes conformes au
AnyObject
protocole, bien sûr):La bonne chose est que vous pouvez spécifier le paramètre à comparer. Par exemple, lorsque vous avez un tableau de tableaux, vous pouvez spécifier la fermeture d'égalité comme
{ $0.count == $1.count }
et le premier tableau ayant la même taille que celui à supprimer est supprimé du tableau.Vous pouvez même raccourcir l'appel de fonction en ayant la fonction as
mutating func removeFirst(equality: (Element) -> Bool) -> Bool
, puis remplacer if-evaluation parequality(item)
et appeler la fonction pararray.removeFirst({ $0 == "Banana" })
par exemple.la source
==
s'agit d'une fonction, vous pouvez également l'appeler comme ceci pour tout type qui implémente==
(comme String, Int, etc.):array.removeFirst("Banana", equality:==)
Pas besoin de prolonger:
la source
En utilisant
indexOf
au lieu d'unfor
ouenumerate
:la source
Peut-être que je n'ai pas compris la question.
Pourquoi cela ne fonctionnerait-il pas?
la source
J'ai finalement fini avec le code suivant.
la source
J'ai réussi à supprimer un
[String:AnyObject]
d'un tableau[[String:AnyObject]]
en implémentant un compte en dehors d'une boucle for pour représenter l'index depuis.find
et je ne suis.filter
pas compatible avec[String:AnyObject]
.la source
Implémentation dans Swift 2:
la source
J'ai pu le faire fonctionner avec:
la source
if(index)
est invalide