¿Por qué no asigna un valor directamente de esta manera:var duplicateArray = originalArray
Dharmesh Kheni
1
Eso no funciona en mi caso. Eso crea otro objeto que es solo una referencia a la misma matriz y termina con 2 variables que hacen referencia a la misma matriz.
user1060500
Respuestas:
176
Las matrices tienen semántica de valor completo en Swift, por lo que no hay necesidad de nada sofisticado.
var duplicateArray = originalArray es todo lo que necesitas.
Si el contenido de su matriz es un tipo de referencia, entonces sí, esto solo copiará los punteros a sus objetos. Para realizar una copia profunda de los contenidos, en su lugar, usaría mapy realizaría una copia de cada instancia. Para las clases Foundation que se ajustan al NSCopyingprotocolo, puede utilizar el copy()método:
let x =[NSMutableArray(),NSMutableArray(),NSMutableArray()]let y = x
let z = x.map { $0.copy()}
x[0]=== y[0]// true
x[0]=== z[0]//false
Tenga en cuenta que aquí existen trampas de las que la semántica de valores de Swift está trabajando para protegerlo; por ejemplo, dado que NSArrayrepresenta una matriz inmutable, su copymétodo solo devuelve una referencia a sí mismo, por lo que la prueba anterior arrojaría resultados inesperados.
Probé esto en el patio de recreo con este código simple var x = [UIView(), UIView(), UIView()] var y = x for i in x { NSLog("%p", i) } println("---") for i in y { NSLog("%p", i) }y obtuve este resultado: 0x7fa82b0009e0 0x7fa82b012660 0x7fa82b012770 ---0x7fa82b0009e0 0x7fa82b012660 0x7fa82b012770 No parece que se esté copiando, ¿sabes por qué?
Phil Niedertscheider
@PNGamingPower: x contiene direcciones. y contiene copias de esas direcciones. Si modifica x [0], y [0] no cambiará. (intente x [0] = x [1], y [0] no cambiará). Por lo tanto, y es una copia profunda de x, pero solo ha copiado los punteros, no a lo que apuntan.
ragnarius
@ragnarius, así que básicamente tenemos que definir qué significa "copiar", ya sea copiando el puntero o el valor. Por lo tanto, esta es la solución para copiar / duplicar la matriz de punteros, pero ¿cómo se duplica la matriz de valores? El objetivo sería x[0] == x[1]pero x[0] === y[0]debería fallar
Phil Niedertscheider
Esta debería ser la respuesta aceptada, ya que la semántica de valores de Array hace que una "copia" de la matriz sea innecesaria.
Scott Ahten
Esto no me funciona. Si sigo ese método, obtengo dos referencias que terminan apuntando a la misma matriz de objetos. Si elimino un elemento de la lista, se refleja en ambas referencias de objeto, ya que la lista no se copió, sino que se hizo referencia al objeto.
user1060500
28
Nate tiene razón. Si está trabajando con matrices primitivas, todo lo que necesita hacer es asignar duplicateArray al originalArray.
En aras de la integridad, si estuviera trabajando con un objeto NSArray, haría lo siguiente para hacer una copia completa de 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
* EDITADO * la edición comienza aquí
Arriba es esencialmente lo mismo que a continuación y, en realidad, usar el operador de igualdad a continuación funcionará mejor ya que la matriz no se copiará a menos que se cambie (esto es por diseño).
agregar o quitar a esta matriz no afectará la matriz original. Sin embargo, cambiar cualquiera de las propiedades de los objetos que contiene la matriz se vería en la matriz original. Porque los objetos en la matriz no son copias (asumiendo que la matriz contiene objetos, no números primitivos).
tiene efecto, lo he probado. hay dos matrices, si u cambia en 1, la segunda se efectúa
Filthy Knight
1
No, no lo hace, a menos que la matriz contenga tipos primitivos en lugar de objetos. Entonces afecta como se indica en la respuesta. Un caso de prueba simple:var array1: [String] = ["john", "alan", "kristen"]; print(array1); var array2 = array1.map { $0 }; print(array2); array2[0] = "james"; print(array1); print(array2);
Si su clase lo apoya NSCopying, entonces duplique una matriz:let z = x.map { $0.copy as! ClassX }
John Pang
Si usa BufferPointers de Swift, esta es la versión que debe usar como copia directa. Antes de cambiar un valor en la matriz original o copiada, Swift copiará los valores del original en la copia y luego continuará. Si usa punteros en su lugar, Swift no lo hará ahora si o cuando se produzcan cambios, por lo que podría terminar cambiando ambas matrices.
Justin Ganzer
16
Para los objetos normales, lo que se puede hacer es implementar un protocolo que admita la copia, y hacer que la clase de objeto implemente este protocolo de esta manera:
Para las subclases, el protocolo no puede garantizar que el requisito init se implemente con el tipo de la subclase. Está declarando un protocolo de copia que implementa la copia para usted, pero aún está implementando clone (), eso no tiene sentido.
Binarian
1
La copia de @iGodric es para los elementos de la colección, y la copia es para toda la colección, disponible cuando se implementa la copia para sus elementos. ¿Tener sentido? Además, el compilador se asegura de que las subclases sigan el protocolo que requiere su padre.
johnbakers
@johnbakers Oh, sí, ahora lo veo. Gracias por la explicación.
Binarian
Implementación muy limpia y evita el ajetreo innecesario de pasar cualquier parámetro en la object'sfunción init
Sylvan D Ash
0
Si desea copiar los elementos de una matriz de algún objeto de clase. Luego, puede seguir el siguiente código sin usar el protocolo NSCopying, pero debe tener un método de inicio que debe tomar todos los parámetros que se requieren para su objeto. Aquí está el código de un ejemplo para probar en el patio de recreo.
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
Respuestas:
Las matrices tienen semántica de valor completo en Swift, por lo que no hay necesidad de nada sofisticado.
var duplicateArray = originalArray
es todo lo que necesitas.Si el contenido de su matriz es un tipo de referencia, entonces sí, esto solo copiará los punteros a sus objetos. Para realizar una copia profunda de los contenidos, en su lugar, usaría
map
y realizaría una copia de cada instancia. Para las clases Foundation que se ajustan alNSCopying
protocolo, puede utilizar elcopy()
método:Tenga en cuenta que aquí existen trampas de las que la semántica de valores de Swift está trabajando para protegerlo; por ejemplo, dado que
NSArray
representa una matriz inmutable, sucopy
método solo devuelve una referencia a sí mismo, por lo que la prueba anterior arrojaría resultados inesperados.fuente
var x = [UIView(), UIView(), UIView()] var y = x for i in x { NSLog("%p", i) } println("---") for i in y { NSLog("%p", i) }
y obtuve este resultado:0x7fa82b0009e0 0x7fa82b012660 0x7fa82b012770 ---0x7fa82b0009e0 0x7fa82b012660 0x7fa82b012770
No parece que se esté copiando, ¿sabes por qué?x[0] == x[1]
perox[0] === y[0]
debería fallarNate tiene razón. Si está trabajando con matrices primitivas, todo lo que necesita hacer es asignar duplicateArray al originalArray.
En aras de la integridad, si estuviera trabajando con un objeto NSArray, haría lo siguiente para hacer una copia completa de un NSArray:
fuente
Hay una tercera opción para la respuesta de Nate:
* EDITADO * la edición comienza aquí
Arriba es esencialmente lo mismo que a continuación y, en realidad, usar el operador de igualdad a continuación funcionará mejor ya que la matriz no se copiará a menos que se cambie (esto es por diseño).
Lea más aquí: https://developer.apple.com/swift/blog/?id=10
* EDITADO * La edición termina aquí
agregar o quitar a esta matriz no afectará la matriz original. Sin embargo, cambiar cualquiera de las propiedades de los objetos que contiene la matriz se vería en la matriz original. Porque los objetos en la matriz no son copias (asumiendo que la matriz contiene objetos, no números primitivos).
fuente
var array1: [String] = ["john", "alan", "kristen"]; print(array1); var array2 = array1.map { $0 }; print(array2); array2[0] = "james"; print(array1); print(array2);
NSCopying
, entonces duplique una matriz:let z = x.map { $0.copy as! ClassX }
Para los objetos normales, lo que se puede hacer es implementar un protocolo que admita la copia, y hacer que la clase de objeto implemente este protocolo de esta manera:
Y luego la extensión Array para clonar:
y eso es todo, para ver el código y una muestra, consulte esta esencia
fuente
object's
función initSi desea copiar los elementos de una matriz de algún objeto de clase. Luego, puede seguir el siguiente código sin usar el protocolo NSCopying, pero debe tener un método de inicio que debe tomar todos los parámetros que se requieren para su objeto. Aquí está el código de un ejemplo para probar en el patio de recreo.
fuente