2015-01-07 13 views
61

Sono un principiante nella lingua Swift.Come posso creare una copia duplicata esatta di un array?

Come posso creare un duplicato esatto di un array?

Non riesco a trovare informazioni sulla duplicazione di un array in Swift.

Ho provato ad utilizzare .copy()

var originalArray = [1, 2, 3, 4] 
var duplicateArray = originalArray.copy() 
+4

perché non si assegna il valore direttamente in questo modo: 'var duplicateArray = originalArray' –

+0

Grazie! Ha funzionato! – Patrick

risposta

121

Gli array hanno una semantica pieno valore a Swift, quindi non c'è bisogno di qualcosa di fantasia.

var duplicateArray = originalArray è tutto ciò che serve.


Se il contenuto del vostro array sono un tipo di riferimento, allora sì, questo sarà solo copiare i puntatori agli oggetti. Per eseguire una copia profonda dei contenuti, si dovrebbe invece utilizzare map ed eseguire una copia di ciascuna istanza. Per le classi della Fondazione conformi al protocollo NSCopying, è possibile utilizzare il metodo copy():

let x = [NSMutableArray(), NSMutableArray(), NSMutableArray()] 
let y = x 
let z = x.map { $0.copy() } 

x[0] === y[0] // true 
x[0] === z[0] // false 

Nota che ci sono insidie ​​qui che la semantica di valore di Swift sono al lavoro per proteggere l'utente da, ad esempio, dal momento che NSArray rappresenta un array immutabili , il suo metodo copy restituisce solo un riferimento a se stesso, quindi il test sopra avrebbe dato risultati imprevisti.

+0

Ho provato questo in parco giochi con questo semplice codice 'var x = [UIView(), UIView(), UIView()] var y = x for i in x { NSLog ("% p", i) } println ("---") for i in {y NSLog ("% p", i) } 'e ho ottenuto questo output:' 0x7fa82b0009e0 0x7fa82b012660 0x7fa82b012770 --- 0x7fa82b0009e0 0x7fa82b012660 0x7fa82b012770 'Non sembra che sia stato copiato, sai perché? –

+0

@PNGamingPower: x contiene indirizzi. y contiene copie di tali indirizzi. Se si modifica x [0], y [0] non cambierà. (prova x [0] = x [1], y [0] non cambierà). Quindi, y è una copia profonda di x.Ma hai solo copiato i puntatori, non quello a cui stanno puntando. – ragnarius

+0

@ragnarius quindi in pratica dobbiamo definire cosa significa "copiare", sia copiando il puntatore che il valore. Quindi questa è la soluzione per copiare/duplicare l'array di puntatori, ma come si duplica la matrice di valori? L'obiettivo sarebbe 'x [0] == x [1]' ma 'x [0] === y [0]' dovrebbe fallire –

20

Nate è corretto. Se si lavora con array primitivi, è sufficiente assegnare duplicateArray a originalArray.

Per ragioni di completezza, se si sta lavorando un oggetto NSArray, si dovrebbe effettuare le seguenti operazioni per fare una copia completa di un NSArray:

var originalArray = [1, 2, 3, 4] as NSArray 

var duplicateArray = NSArray(array:originalArray, copyItems: true) 
+0

Questo è fantastico! Grazie! – Patrick

+0

Ottima risposta, grazie! – RainCast

10

Per gli oggetti normali che cosa si può fare è quello di attuare un protocollo che supporta la copia, e rendere la classe oggetto implementa questo protocollo come questo:

protocol Copying { 
    init(original: Self) 
} 

extension Copying { 
    func copy() -> Self { 
     return Self.init(original: self) 
    } 
} 

e poi l'estensione Array per la clonazione:

extension Array where Element: Copying { 
    func clone() -> Array { 
     var copiedArray = Array<Element>() 
     for element in self { 
      copiedArray.append(element.copy()) 
     } 
     return copiedArray 
    } 
} 

e che è praticamente esso, per visualizzare il codice e un controllo a campione questo gist

+0

Questo ha risparmiato molto tempo, grazie. – Abhijit

+0

Per le sottoclassi il protocollo non può garantire che il requisito init sia implementato con il tipo della sottoclasse. Stai dichiarando un protocollo di copia che implementa la copia per te, ma stai ancora implementando clone(), che non ha senso. – Binarian

+1

@iGodric copy è per gli elementi nella raccolta e clone è per l'intera raccolta, disponibile quando la copia è implementata per i suoi elementi. Ha senso? Inoltre, il compilatore assicura che le sottoclassi seguano il protocollo richiesto dal genitore. – johnbakers

8

C'è una terza opzione per la risposta di Nate:

let z = x.map { $0 } // different array with same objects 

* A CURA * modificare comincia qui

Sopra è essenzialmente lo stesso di seguito e in realtà utilizzando l'operatore di uguaglianza di seguito si esibirà meglio poiché l'array non verrà copiato a meno che non venga modificato (questo è di progettazione).

let z = x 

Per saperne di più qui: https://developer.apple.com/swift/blog/?id=10

* A CURA * modificare finisce qui

aggiunta o la rimozione di questo array non influenzerà la matrice originale. Tuttavia, cambiando qualsiasi proprietà dell'oggetto che l'array detiene si vedrebbe nell'array originale. Perché gli oggetti nell'array non sono copie (supponendo che gli oggetti hold dell'array non siano numeri primitivi).

+0

ha effetto, l'ho provato. ci sono due matrici, se si cambia in 1, il secondo viene effettuato –

+0

No, a meno che l'array non contenga tipi primitivi invece di oggetti. Quindi influisce come indicato nella risposta. Un semplice caso di test: 'var array1: [String] = [" john "," alan "," kristen "]; stampa (matrice1); var array2 = array1.map {$ 0}; stampa (matrice2); array2 [0] = "james"; stampa (matrice1); print (array2); ' – oyalhi

+0

Vedere questo elenco che ho creato per un esempio migliore utilizzando una classe personalizzata: https://gist.github.com/oyalhi/3b9a415cf20b5b54bb3833817db059ce – oyalhi

Problemi correlati