pourquoi n'attribuez-vous pas une valeur directement comme ceci:var duplicateArray = originalArray
Dharmesh Kheni
1
Cela ne fonctionne pas dans mon cas. Cela crée un autre objet qui n'est qu'une référence au même tableau et vous vous retrouvez avec 2 variables référençant le même tableau.
user1060500
Réponses:
176
Les tableaux ont une sémantique pleine valeur dans Swift, il n'y a donc pas besoin de quelque chose d'extraordinaire.
var duplicateArray = originalArray est tout ce dont vous avez besoin.
Si le contenu de votre tableau est un type de référence, alors oui, cela ne copiera que les pointeurs vers vos objets. Pour effectuer une copie complète du contenu, vous utiliseriez mapet exécuteriez plutôt une copie de chaque instance. Pour les classes Foundation conformes au NSCopyingprotocole, vous pouvez utiliser la copy()méthode:
let x =[NSMutableArray(),NSMutableArray(),NSMutableArray()]let y = xlet z = x.map { $0.copy()}
x[0]=== y[0]// truex[0]=== z[0]//false
Notez qu'il y a des pièges contre lesquels la sémantique des valeurs de Swift travaille pour vous protéger - par exemple, étant donné que NSArrayreprésente un tableau immuable, sa copyméthode renvoie simplement une référence à elle-même, de sorte que le test ci-dessus donnerait des résultats inattendus.
J'ai essayé cela dans la cour de récréation avec ce code simple var x = [UIView(), UIView(), UIView()] var y = x for i in x { NSLog("%p", i) } println("---") for i in y { NSLog("%p", i) }et j'ai obtenu cette sortie: 0x7fa82b0009e0 0x7fa82b012660 0x7fa82b012770 ---0x7fa82b0009e0 0x7fa82b012660 0x7fa82b012770 ne semble pas être copié, savez-vous pourquoi?
Phil Niedertscheider
@PNGamingPower: x contient des adresses. y contient des copies de ces adresses. Si vous modifiez x [0], y [0] ne changera pas. (essayez x [0] = x [1], y [0] ne changera pas). Ainsi, y est une copie complète de x, mais vous n'avez copié que les pointeurs, pas ce qu'ils pointent.
ragnarius
@ragnarius donc fondamentalement, nous devons définir ce que signifie "copier", soit en copiant le pointeur, soit en copiant la valeur. C'est donc la solution pour copier / dupliquer le tableau de pointeurs, mais comment dupliquer le tableau de valeurs? Le but serait x[0] == x[1]mais x[0] === y[0]devrait échouer
Phil Niedertscheider
Cela devrait être la réponse acceptée, car la sémantique des valeurs de Array rend une "copie" du tableau inutile.
Scott Ahten
Cela ne fonctionne pas pour moi. Si je suis cette méthode, j'obtiens deux références qui finissent par pointer vers le même tableau d'objets. Si je supprime un élément de la liste, il est reflété dans les deux références d'objet car la liste n'a pas été copiée, mais l'objet a simplement été référencé.
user1060500
28
Nate a raison. Si vous travaillez avec des tableaux primitifs, tout ce que vous avez à faire est d'assigner duplicateArray à l'originalArray.
Par souci d'exhaustivité, si vous travailliez sur un objet NSArray, procédez comme suit pour faire une copie complète d'un NSArray:
var originalArray =[1,2,3,4]asNSArrayvar duplicateArray =NSArray(array:originalArray, copyItems:true)
let z = x.map { $0}// different array with same objects
* EDITED * La modification commence ici
Ci-dessus est essentiellement le même que ci-dessous et l'utilisation de l'opérateur d'égalité ci-dessous fonctionnera mieux car le tableau ne sera pas copié à moins qu'il ne soit modifié (c'est par conception).
l'ajout ou la suppression de ce tableau n'affectera pas le tableau d'origine. Cependant, la modification des propriétés des objets contenues dans le tableau serait visible dans le tableau d'origine. Parce que les objets du tableau ne sont pas des copies (en supposant que le tableau contient des objets, pas des nombres primitifs).
cela fait effet, je l'ai testé. il y a deux tableaux, si vous changez en 1, le second est effectué
Filthy Knight
1
Non, ce n'est pas le cas, à moins que le tableau ne contienne des types primitifs au lieu d'objets. Ensuite, cela affecte comme indiqué dans la réponse. Un cas de test simple:var array1: [String] = ["john", "alan", "kristen"]; print(array1); var array2 = array1.map { $0 }; print(array2); array2[0] = "james"; print(array1); print(array2);
Si votre classe prend en charge NSCopying, alors dupliquez un tableau:let z = x.map { $0.copy as! ClassX }
John Pang
Si vous utilisez les BufferPointers de Swift, c'est la version que vous devez utiliser comme copie directe. Avant de modifier une valeur dans l'original ou dans le tableau copié, Swift copiera les valeurs de l'original dans la copie, puis continuera. Si vous utilisez plutôt des pointeurs, Swift ne le fera pas maintenant si ou quand des changements ont lieu, vous pourriez donc finir par changer les deux tableaux.
Justin Ganzer le
16
Pour les objets normaux, ce qui peut être fait est d'implémenter un protocole prenant en charge la copie et de faire en sorte que la classe d'objets implémente ce protocole comme ceci:
Pour les sous-classes, le protocole ne peut pas garantir que l'exigence init est implémentée avec le type de la sous-classe. Vous déclarez un protocole de copie qui implémente copy pour vous, mais vous implémentez toujours clone (), cela n'a pas de sens.
Binarian
1
La copie @iGodric concerne les éléments de la collection et le clone concerne l'ensemble de la collection, disponible lorsque la copie est implémentée pour ses éléments. Ça a du sens? En outre, le compilateur garantit que les sous-classes suivent le protocole requis par leur parent.
johnbakers
@johnbakers Oh ouais, maintenant je le vois. Merci pour l'explication.
Binarian
Implémentation très propre et évite l'agitation inutile de passer des paramètres dans la object'sfonction init
Sylvan D Ash
0
Si vous souhaitez copier les éléments d'un tableau d'un objet de classe. Ensuite, vous pouvez suivre le code ci-dessous sans utiliser le protocole NSCopying mais vous devez avoir une méthode init qui devrait prendre tous les paramètres requis pour votre objet. Voici le code d'un exemple à tester sur terrain de jeu.
class ABC {var a =0func myCopy()-> ABC {return ABC(value:self.a)}init(value:Int){self.a = value
}}var arrayA:[ABC]=[ABC(value:1)]var arrayB:[ABC]= arrayA.map { $0.myCopy()}
arrayB.first?.a =2
print(arrayA.first?.a)//Prints 1
print(arrayB.first?.a)//Prints2
var duplicateArray = originalArray
Réponses:
Les tableaux ont une sémantique pleine valeur dans Swift, il n'y a donc pas besoin de quelque chose d'extraordinaire.
var duplicateArray = originalArray
est tout ce dont vous avez besoin.Si le contenu de votre tableau est un type de référence, alors oui, cela ne copiera que les pointeurs vers vos objets. Pour effectuer une copie complète du contenu, vous utiliseriez
map
et exécuteriez plutôt une copie de chaque instance. Pour les classes Foundation conformes auNSCopying
protocole, vous pouvez utiliser lacopy()
méthode:Notez qu'il y a des pièges contre lesquels la sémantique des valeurs de Swift travaille pour vous protéger - par exemple, étant donné que
NSArray
représente un tableau immuable, sacopy
méthode renvoie simplement une référence à elle-même, de sorte que le test ci-dessus donnerait des résultats inattendus.la source
var x = [UIView(), UIView(), UIView()] var y = x for i in x { NSLog("%p", i) } println("---") for i in y { NSLog("%p", i) }
et j'ai obtenu cette sortie:0x7fa82b0009e0 0x7fa82b012660 0x7fa82b012770 ---0x7fa82b0009e0 0x7fa82b012660 0x7fa82b012770
ne semble pas être copié, savez-vous pourquoi?x[0] == x[1]
maisx[0] === y[0]
devrait échouerNate a raison. Si vous travaillez avec des tableaux primitifs, tout ce que vous avez à faire est d'assigner duplicateArray à l'originalArray.
Par souci d'exhaustivité, si vous travailliez sur un objet NSArray, procédez comme suit pour faire une copie complète d'un NSArray:
la source
Il y a une troisième option à la réponse de Nate:
* EDITED * La modification commence ici
Ci-dessus est essentiellement le même que ci-dessous et l'utilisation de l'opérateur d'égalité ci-dessous fonctionnera mieux car le tableau ne sera pas copié à moins qu'il ne soit modifié (c'est par conception).
En savoir plus ici: https://developer.apple.com/swift/blog/?id=10
* EDITED * la modification se termine ici
l'ajout ou la suppression de ce tableau n'affectera pas le tableau d'origine. Cependant, la modification des propriétés des objets contenues dans le tableau serait visible dans le tableau d'origine. Parce que les objets du tableau ne sont pas des copies (en supposant que le tableau contient des objets, pas des nombres primitifs).
la source
var array1: [String] = ["john", "alan", "kristen"]; print(array1); var array2 = array1.map { $0 }; print(array2); array2[0] = "james"; print(array1); print(array2);
NSCopying
, alors dupliquez un tableau:let z = x.map { $0.copy as! ClassX }
Pour les objets normaux, ce qui peut être fait est d'implémenter un protocole prenant en charge la copie et de faire en sorte que la classe d'objets implémente ce protocole comme ceci:
Et puis l'extension Array pour le clonage:
et c'est à peu près tout, pour afficher le code et un échantillon, vérifiez ce point essentiel
la source
object's
fonction initSi vous souhaitez copier les éléments d'un tableau d'un objet de classe. Ensuite, vous pouvez suivre le code ci-dessous sans utiliser le protocole NSCopying mais vous devez avoir une méthode init qui devrait prendre tous les paramètres requis pour votre objet. Voici le code d'un exemple à tester sur terrain de jeu.
la source