por que você não atribui valor diretamente assim:var duplicateArray = originalArray
Dharmesh Kheni
1
Isso não funciona no meu caso. Isso cria outro objeto que é apenas uma referência ao mesmo array e você acaba com 2 variáveis referenciando o mesmo array.
user1060500
Respostas:
176
Os arrays têm semântica de valor total em Swift, portanto, não há necessidade de nada sofisticado.
var duplicateArray = originalArray é tudo o que você precisa.
Se o conteúdo do seu array for um tipo de referência, então sim, isso apenas copiará os ponteiros para seus objetos. Para realizar uma cópia profunda do conteúdo, você deve usar mape realizar uma cópia de cada instância. Para classes Foundation que estão em conformidade com o NSCopyingprotocolo, você pode usar o 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
Observe que há armadilhas aqui contra as quais a semântica de valor do Swift está trabalhando para protegê-lo - por exemplo, como NSArrayrepresenta uma matriz imutável, seu copymétodo apenas retorna uma referência para si mesmo, portanto, o teste acima produziria resultados inesperados.
Tentei fazer isso no playground com um código simples var x = [UIView(), UIView(), UIView()] var y = x for i in x { NSLog("%p", i) } println("---") for i in y { NSLog("%p", i) }e obtive esta saída: 0x7fa82b0009e0 0x7fa82b012660 0x7fa82b012770 ---0x7fa82b0009e0 0x7fa82b012660 0x7fa82b012770 Não parece que está sendo copiado, sabe por quê?
Phil Niedertscheider
@PNGamingPower: x contém endereços. y contém cópias desses endereços. Se você alterar x [0], y [0] não mudará. (tente x [0] = x [1], y [0] não mudará). Portanto, y é uma cópia profunda de x. Mas você apenas copiou os ponteiros, não para onde eles estão apontando.
ragnarius
@ragnarius então basicamente temos que definir o que "copiar" significa, copiando o ponteiro ou o valor. Portanto, esta é a solução para copiar / duplicar a matriz de ponteiros, mas como você duplica a matriz de valores? O objetivo seria, x[0] == x[1]mas x[0] === y[0]deve falhar
Phil Niedertscheider
Essa deve ser a resposta aceita, já que a semântica de valor do Array torna desnecessária uma "cópia" do array.
Scott Ahten
Isso não funciona para mim. Se eu seguir esse método, obtenho duas referências que acabam apontando para a mesma matriz de objetos. Se eu remover um item da lista, ele será refletido em ambas as referências de objeto, uma vez que a lista não foi copiada, mas sim o objeto apenas referenciado.
user1060500
28
Nate está correto. Se estiver trabalhando com matrizes primitivas, tudo o que você precisa fazer é atribuir duplicateArray ao originalArray.
Para fins de integridade, se você estivesse trabalhando em um objeto NSArray, faria o seguinte para fazer uma cópia completa de um 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 * a edição começa aqui
Acima é essencialmente o mesmo que abaixo e, na verdade, o uso do operador de igualdade abaixo terá um desempenho melhor, pois a matriz não será copiada a menos que seja alterada (isso é por design).
adicionar ou remover a esta matriz não afetará a matriz original. No entanto, a alteração de qualquer uma das propriedades dos objetos que a matriz contém seria vista na matriz original. Porque os objetos na matriz não são cópias (assumindo que a matriz contém objetos, não números primitivos).
faz efeito, eu testei. existem duas matrizes, se u mudar em 1, a segunda é efetuada
Filthy Knight
1
Não, a menos que array contenha tipos primitivos em vez de objetos. Então, isso afeta conforme declarado na resposta. Um caso de teste simples:var array1: [String] = ["john", "alan", "kristen"]; print(array1); var array2 = array1.map { $0 }; print(array2); array2[0] = "james"; print(array1); print(array2);
Se sua classe apoiar NSCopying, duplique uma matriz:let z = x.map { $0.copy as! ClassX }
John Pang
Se estiver usando BufferPointers do Swift, esta é a versão que você deve usar como cópia direta. Antes de alterar um valor no array original ou copiado, o Swift irá copiar os valores do original para a cópia e então continuar. Se você usar ponteiros em vez disso, o Swift não usará agora se ou quando as alterações ocorrerem, portanto, você pode acabar alterando ambos os arrays.
Justin Ganzer
16
Para objetos normais, o que pode ser feito é implementar um protocolo que suporte cópia, e fazer com que a classe de objeto implemente este protocolo assim:
Para subclasses, o protocolo não pode garantir que o requisito init seja implementado com o tipo da subclasse. Você está declarando um protocolo de cópia que implementa copy para você, mas ainda está implementando clone (), isso não faz sentido.
Binarian
1
@iGodric copy é para elementos da coleção e clone é para toda a coleção, disponível quando a cópia é implementada para seus elementos. Faz sentido? Além disso, o compilador garante que as subclasses sigam o protocolo que seu pai requer.
johnbakers
@johnbakers Oh sim, agora eu vejo. Obrigado pela explicação.
Binarian
Implementação muito limpa e evita a confusão desnecessária de passar quaisquer parâmetros na object'sfunção init
Sylvan D Ash
0
Se você deseja copiar os itens de um array de algum objeto de classe. Então você pode seguir o código abaixo sem usar o protocolo NSCopying, mas você precisa ter um método init que deve levar todos os parâmetros que são necessários para o seu objeto. Aqui está o código de um exemplo para testar no playground.
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
Respostas:
Os arrays têm semântica de valor total em Swift, portanto, não há necessidade de nada sofisticado.
var duplicateArray = originalArray
é tudo o que você precisa.Se o conteúdo do seu array for um tipo de referência, então sim, isso apenas copiará os ponteiros para seus objetos. Para realizar uma cópia profunda do conteúdo, você deve usar
map
e realizar uma cópia de cada instância. Para classes Foundation que estão em conformidade com oNSCopying
protocolo, você pode usar ocopy()
método:Observe que há armadilhas aqui contra as quais a semântica de valor do Swift está trabalhando para protegê-lo - por exemplo, como
NSArray
representa uma matriz imutável, seucopy
método apenas retorna uma referência para si mesmo, portanto, o teste acima produziria resultados inesperados.fonte
var x = [UIView(), UIView(), UIView()] var y = x for i in x { NSLog("%p", i) } println("---") for i in y { NSLog("%p", i) }
e obtive esta saída:0x7fa82b0009e0 0x7fa82b012660 0x7fa82b012770 ---0x7fa82b0009e0 0x7fa82b012660 0x7fa82b012770
Não parece que está sendo copiado, sabe por quê?x[0] == x[1]
masx[0] === y[0]
deve falharNate está correto. Se estiver trabalhando com matrizes primitivas, tudo o que você precisa fazer é atribuir duplicateArray ao originalArray.
Para fins de integridade, se você estivesse trabalhando em um objeto NSArray, faria o seguinte para fazer uma cópia completa de um NSArray:
fonte
Há uma terceira opção para a resposta de Nate:
* EDITADO * a edição começa aqui
Acima é essencialmente o mesmo que abaixo e, na verdade, o uso do operador de igualdade abaixo terá um desempenho melhor, pois a matriz não será copiada a menos que seja alterada (isso é por design).
Leia mais aqui: https://developer.apple.com/swift/blog/?id=10
* EDITADO * a edição termina aqui
adicionar ou remover a esta matriz não afetará a matriz original. No entanto, a alteração de qualquer uma das propriedades dos objetos que a matriz contém seria vista na matriz original. Porque os objetos na matriz não são cópias (assumindo que a matriz contém objetos, não números primitivos).
fonte
var array1: [String] = ["john", "alan", "kristen"]; print(array1); var array2 = array1.map { $0 }; print(array2); array2[0] = "james"; print(array1); print(array2);
NSCopying
, duplique uma matriz:let z = x.map { $0.copy as! ClassX }
Para objetos normais, o que pode ser feito é implementar um protocolo que suporte cópia, e fazer com que a classe de objeto implemente este protocolo assim:
E então a extensão Array para clonagem:
e isso é basicamente isso, para ver o código e uma amostra, verifique esta essência
fonte
object's
função initSe você deseja copiar os itens de um array de algum objeto de classe. Então você pode seguir o código abaixo sem usar o protocolo NSCopying, mas você precisa ter um método init que deve levar todos os parâmetros que são necessários para o seu objeto. Aqui está o código de um exemplo para testar no playground.
fonte